A. Cleaning the 5W data

 

This first section details an example of the code necessary for cleaning a 5W dataset in R. 5W data is typically messy and in wide format. Additionally, data wrangling is time consuming and an inefficient use of a specialist’s time. The code presented below intends to demonstrate that this monthly (or more frequent) occurence can be greatly automated, allowing for more timely and accurate analysis as well as creating the space for more tailored reporting.

 

1. Reading in the dataset

# specifying column types 
act_col_types <- c("date", "date", "text", "text","text","text",
                   "text","text","text","text","text","text","text",
                   "numeric", "numeric", "text","text","text",
                   "text","text","text", "numeric", "text", 
                   "date", "date", "text", "numeric", "numeric",
                   "logical", "numeric", "numeric", "numeric",
                   "numeric", "numeric", "numeric", "numeric",
                   "numeric", "numeric", "numeric", "numeric",
                   "numeric", "numeric", "numeric")

# you're gonna have to live with the error messages,
# since you can't slice before read_excel() argument

act1<- read_excel("database activities 5W.xlsx", 
                     sheet = "data", 
                     skip = 1, 
                     col_types = act_col_types) %>% 
  clean_names() %>% 
  remove_empty() %>% 
  slice(-c(1)) %>% # removes the second row
  slice(-c(12055)) # removes the grand total

 

2. String Manipulation and Recoding

2a. Renaming Columns

Instead of showing a long vector of column names, here is a glimpse() of the renamed dataset:

## Rows: 12,054
## Columns: 43
## $ fecha_reportado_cluster           <dttm> NA, NA, NA, NA, NA, NA, NA, NA, NA,~
## $ mes_reportado                     <dttm> 2020-01-31, 2020-01-31, 2020-01-31,~
## $ codigo_de_proyecto                <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, ~
## $ nombre_del_proyecto               <chr> "Todos y Todas a la Escuela", "Todos~
## $ organizacion_lider                <chr> "UNICEF - Fondo de las Naciones Unid~
## $ organizacion_implementadora       <chr> "SOCIO 1", "SOCIO 1", "SOCIO 1", "SO~
## $ estado                            <chr> "Zulia", "Zulia", "Zulia", "Distrito~
## $ pcode1                            <chr> "VE23", "VE23", "VE23", "VE01", "VE0~
## $ municipio                         <chr> "Maracaibo", "Maracaibo", "Maracaibo~
## $ pcode2                            <chr> "VE2313", "VE2313", "VE2313", "VE010~
## $ parroquia                         <chr> "Luis Hurtado Higuera", "Luis Hurtad~
## $ pcode3                            <chr> "VE231312", "VE231312", "VE231312", ~
## $ ubicacion                         <chr> "E. T. Dr. Luis Razetti  Fe Y Alegrí~
## $ latitud                           <dbl> 10.596934, 10.596934, 10.596934, 10.~
## $ longitud                          <dbl> -71.66896, -71.66896, -71.66896, -66~
## $ actividad_full                    <chr> "CLEDU/CA2.09: Formación docente y o~
## $ actividad_codigo                  <chr> "CA2.09", "CA2.09", "CA2.09", "CA2.0~
## $ actividad_desc                    <chr> "Formación docente y otro personal e~
## $ actividad_codigo_desc             <chr> "CA2.09: Formación docente y otro pe~
## $ act_covid                         <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, ~
## $ unidad                            <chr> "#Personas", "#Personas", "#Personas~
## $ cantidad_del_mes                  <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, ~
## $ recurrente_beneficiarios          <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, ~
## $ fecha_de_inicio                   <dttm> 2019-10-22, 2019-10-15, 2020-01-13,~
## $ fecha_prevista_finalizacion       <dttm> 2020-01-20, 2020-01-13, 2020-01-13,~
## $ estatus_actividad                 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, ~
## $ total_beneficiarios               <dbl> 16, 13, 41, 2, 1, 25, 19, 19, 17, 17~
## $ check_beneficiaries               <dbl> 16, 13, 41, 2, 1, 25, 19, 19, 17, 17~
## $ t_f_ben                           <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ~
## $ percent_poblacion_indigena        <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, ~
## $ percent_personas_con_discapacidad <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, ~
## $ m_0_3                             <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ m_3_6                             <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ m_7_12                            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ m_12_17                           <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ m_18_19                           <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ f_0_3                             <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ f_3_6                             <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ f_7_12                            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ f_12_17                           <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ f_18_19                           <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
## $ f_mayores_de_19                   <dbl> 11, 4, 41, 2, 1, 20, 10, 10, 5, 8, 3~
## $ m_mayores_de_19                   <dbl> 5, 9, 0, 0, 0, 5, 9, 9, 12, 9, 13, 1~

2b. Removing accents and standardising case

# function to remove accents
rm_accent <- function(colns){
  colns <- stri_trans_general(colns, "Latin-ASCII")
}

# removing accents
act1 <- act1 %>% 
  mutate(estado    = rm_accent(str_to_upper(estado)), # string to upper and rm_accent
         municipio = rm_accent(str_to_upper(municipio)),
         parroquia = rm_accent(str_to_upper(parroquia)),
         ubicacion = rm_accent(str_to_upper(ubicacion)),
         actividad_desc = rm_accent(str_to_upper(actividad_desc)))

2c. Recoding erroneous data

And mutating a new date column just with the month

# recoding 
act1 <- act1 %>% 
  mutate(recurrente_beneficiarios = 
           recode(recurrente_beneficiarios, 
            "no" = FALSE, "No" = FALSE, "Si" = TRUE, "si" = TRUE, "sí" = TRUE, "Sí" = TRUE),
         act_covid = recode(act_covid, 
            "no" = FALSE, "No" = FALSE, "Si" = TRUE, "si" = TRUE, "sí" = TRUE, "Sí" = TRUE)) %>% 
  replace_na(list(recurrente_beneficiarios = FALSE, act_covid = FALSE)) 

# recoding estatus_actividad
act1$estatus_actividad <- act1$estatus_actividad %>% 
  str_replace_all(c("En ejecucion" = "ejecucion", 
                    "en ejecución" = "ejecucion", 
                    "en Ejecución" = "ejecucion",
                    "En ejecución" = "ejecucion",
                    "En Ejecución" = "ejecucion",
                    "finalizada" = "finalizada",
                    "Finalizada" = "finalizada"))

# create a new variable of last day of month only 
act1$mes_solo <- ceiling_date(act1$mes_reportado, "month") - days(1)

 

3. Cleaning locations

3a. Read in locations.csv

And check if you need to update it

locations <- read_csv("locations.csv") %>%
  mutate(estado    = rm_accent(str_to_upper(estado)),
         municipio = rm_accent(str_to_upper(municipio)),
         parroquia = rm_accent(str_to_upper(parroquia)),
         ubicacion = rm_accent(str_to_upper(ubicacion)))
# see if you need to update locations 
 locations_add <- act1 %>% 
   select(estado, pcode1, municipio, pcode2, parroquia, pcode3, ubicacion) %>% 
   distinct() %>% 
   anti_join(locations, by = "ubicacion")

3b. Splitting the dataset into clean and dirty

This section reads in the locations reference dataset then uses it to clean adm_dirty and rewrites it to adm_dirty1. The distinct() call at the end is to ensure that no duplicates are included as the left_join() argument will product duplicates. After which, adm_clean and adm_dirty1 are combined into act2.

As a note, there is a to include a set of new pcodes – “todo municipio” and “todo estado”.

# splitting into two datasets, one clean one dirty. 
adm_dirty <- act1 %>% 
  filter(is.na(estado) | is.na(pcode1) |
         is.na(municipio) | is.na(pcode2) |
         is.na(parroquia) | is.na(pcode3))

adm_clean <- act1 %>% 
  filter(!is.na(estado) & !is.na(pcode1) &
         !is.na(municipio) & !is.na(pcode2) &
         !is.na(parroquia) & !is.na(pcode3)) 

3c. Fill in missing values with coalesce()

# filling in missing values
adm_dirty <- adm_dirty %>% 
  left_join(locations, by = "ubicacion") %>% 
  mutate(estado    = coalesce(estado.x, estado.y),
         pcode1    = coalesce(pcode1.x, pcode1.y),
         municipio = coalesce(municipio.x, municipio.y),
         pcode2    = coalesce(pcode2.x, pcode2.y),
         parroquia = coalesce(parroquia.x, parroquia.y),
         pcode3    = coalesce(pcode3.x, pcode3.y)) %>% 
  select(-estado.x, -estado.y, -pcode1.x, -pcode1.y,
         -municipio.x, -municipio.y, -pcode2.x, -pcode2.y,
         -parroquia.x, -parroquia.y, -pcode3.x, -pcode3.y) %>% 
  distinct() # removing duplicate rows from the join 

# bind_rows() does not care about column sequence 
# but put adm_clean first so that the original order is preserved
act2 <- bind_rows(adm_clean, adm_dirty)

3d. Error checking the join

printing total beneficiaries for act1 and act2, followed by nrow() for both.

## [1] 28965878
## [1] 28965878
## [1] 12054
## [1] 12054

 

4. Beneficiary disaggregation

This is to check that total_beneficiarios is equal to the sum of all disaggregated columns. First, we mutate a new column by summing all the disaggregated beneficiaries and calling it total_ben_check. The next function prints the differences between total_ben_check and total_beneficiarios. Finally, we mutate a new column in the dataset called no_esp_ben or beneficiarios no especificados to collect the differences and ensure that we do not lose them.

# mutating bencheck and unspecified beneficiaries columns 
act2 <- act2 %>% 
  mutate(total_ben_check = select(., m_0_3:m_mayores_de_19) %>%  rowSums(na.rm = TRUE), 
         no_esp_ben      = round(total_beneficiarios) - round(total_ben_check)) 

Next, we print rows where the sum of disaggregated beneficiaries do not match the totals reported in the total_beneficiarios column.

Undisaggregated beneficiaries
organizacion_implementadora actividad_desc ubicacion total_ben_check total_beneficiarios no_esp_ben
SOCIO 2 PROMOCION MENSAJES CLAVES PARA LA COMUNIDAD ESCOLAR U.E.C. DIVINA PASTORA (CATEDRAL) 0 244 244
SOCIO 4 INICIATIVAS PARA REINSERCION EDUCATIVA DE NNA FUERA DE LA ESCUELA U.E. SAN JOSE DE COTIZA 18 26 8
SOCIO 6 FORMACION DOCENTE Y OTRO PERSONAL EDUCATIVO MINISTERIO DEL PODER POPULAR PARA LA EDUCACION 0 398 398
SOCIO 6 FORMACION DOCENTE Y OTRO PERSONAL EDUCATIVO CLUSTER DE EDUCACION 0 146 146

 

5. Outputs

5a. Cleaned wide version

# timestamp for all the files to be written below
now <- Sys.time()

For submissions to OCHA, this one aligns with their format

# turn on eval if you want the file
filename_wide <- paste0(format(now, "%y%m%d_%H%M_"), "5W_wide.csv")
write_csv(act2, filename_wide)

5b. Unique beneficiaries

This section pivots the dataset longer into tidy data which, with one observation per instance of age and sex; this is necessary for easy plotting and additional operations. Additionally, rows with no beneficiaries are filtered out.

The dataset u_ben is created by taking the highest number of beneficiaries by age and sex group by location. The columns are then filtered down to create a more usable dataset. We will use this dataset for any operations related to unique beneficiaries (individuals), including comparisons with census data to determine reach and coverage. Please note that not all activities will be represented in this dataset as only the max of beneficiaries per disaggregation group per location was selected.

# pivoting longer and creating new dataframe
  
u_ben <- act2 %>% 
  select(-t_f_ben, -total_ben_check) %>% # remember to drop them
  relocate(mes_solo) %>% # moves mes_solo to the first variable
  pivot_longer(m_0_3:no_esp_ben, 
               names_to = "desagregacion", values_to = "beneficiarios") %>% 
  filter(recurrente_beneficiarios == FALSE) %>%
  filter(beneficiarios != 0) %>% # empty cells are 0 in the 5W table
  group_by(ubicacion, desagregacion) %>% 
  slice(which.max(beneficiarios)) %>% 
  ungroup() %>% 
  select(mes_solo, estado, pcode1, municipio, pcode2,parroquia, pcode3, 
         ubicacion, latitud, longitud,
         desagregacion, beneficiarios)
# writing csv of u_ben with datestamp
# turn on eval if you want the file 
filename_u_ben <- paste0(format(now, "%y%m%d_%H%M_"), "u_ben.csv")
write_csv(u_ben, filename_u_ben)

5c. Beneficiaries by activity

The dataset act_ben is for activity totals. Only the rows marked as recurrente_beneficiarios == FALSE have been selected. The first instance of recurring beneficiaires is marked FALSE, with all subsequent entries being marked TRUE. Similar to u_ben, it has also been pivoted longer into tidy data.

Please not that we can only assure that there no duplications within locations as specific locations might have been targetted by more than one activity. For geographic operations, please use u_ben.

# This is the dataset for beneficiaries
act_ben <- act2 %>%
  select(-t_f_ben, -total_ben_check) %>% # remember to drop them
  relocate(mes_solo) %>% # moves mes_solo to the first variable
  filter(recurrente_beneficiarios == FALSE) %>%
  pivot_longer(m_0_3:no_esp_ben, 
               names_to = "desagregacion", values_to = "beneficiarios") %>% 
  filter(beneficiarios != 0) %>% # empty cells are 0 in the 5W table
  group_by(ubicacion, desagregacion) %>% 
  select(mes_solo, nombre_del_proyecto, organizacion_implementadora, 
         estado, pcode1, municipio, pcode2, parroquia, pcode3, 
         ubicacion, latitud, longitud,
         actividad_codigo, actividad_desc, act_covid,
         desagregacion, beneficiarios)
# writing csv act_ben with datestamp
# turn on eval if you want the file 
filename_act_ben <- paste0(format(now, "%y%m%d_%H%M_"), "act_ben.csv")
write_csv(act_ben, filename_act_ben)

5d. Comparing u_ben, act_ben and difference

## [1] 3660609
## [1] 5673040
## [1] 2012431

 

B. Reporting on the 5W data

 

This is an entirely automated report – all charts and tables, as well as all figures within the report have been generated from the data, with no manual input. This report makes use of the outputs of the 5W_cleaning section above. This set of 5W data pertains to the Education Cluster in Venezuela and has had partner information removed. Code will not be shown in this section.

 

1. Summary of beneficiaries by activity, with sex ratio

actividad total percent_of_total male female sex_ratio
DISTRIBUCION DE KITS DE MATERIALES ESCOLARES 471,568 50.91 232,197 239,372 0.97
ALIMENTACION ESCOLAR 156,472 16.89 72,035 84,437 0.85
EDUCACION A DISTANCIA 132,258 14.28 64,240 68,018 0.94
APOYO PSICOEDUCATIVO PARA NNA 120,887 13.05 54,859 66,028 0.83
FORMACION DOCENTE Y OTRO PERSONAL EDUCATIVO 17,238 1.86 3,470 13,224 0.26
ACTIVIDADES CON ADOLESCENTES Y JOVENES DE NIVELACION, HABILIDADES PARA LA VIDA Y CAPACITACION TECNICA 14,016 1.51 6,336 7,680 0.82
BECAS Y OTROS INCENTIVOS PARA DOCENTES Y PERSONAL 5,744 0.62 1,572 4,172 0.38
ACTIVIDADES RECREATIVAS 4,317 0.47 1,998 2,319 0.86
INICIATIVAS PARA REINSERCION EDUCATIVA DE NNA FUERA DE LA ESCUELA 3,869 0.42 2,114 1,755 1.2

A total of 728,408 individuals have been reached to date. In terms of frequencies (inclusive of double counting), 926,369 have been reached.

Additionally, the 4,746,671 beneficiary frequencies reached by the activity PROMOCION MENSAJES CLAVES PARA LA COMUNIDAD ESCOLAR have been removed from the totals in this report as the activity consists of solely radio messaging.

 

2. Beneficiaries by age group

figures are unique beneficiaries/individuals

 

2a. Beneficiaries by age compared to 2017 Enrollment

With reference to the 2017 Matricula dataset, we can see that the Education programme has reached an overall average of 9% of schoolgoing children aged 3-17 nationwide. Children aged 3-17 consitute 88% of all UNICEF beneficiaries.

Edad grupo beneficiarios matricula2017 percent_total
3-6 121,169 1,438,475 8.423
7-12 352,808 3,252,505 10.85
12-17 169,771 2,205,724 7.697

 

3. Changes since previous month

The number of individuals reached has increased by 175,005 in the past month, reaching a total of 728,408. The number of beneficiary frequencies reached has increased by 218,443 in the same period, reaching a total of 926,369.

 

3a. Progress by activity by month

mouse over to see details

Progress in recent months has largely been due to the distribution of education kits and distance learning.

 

4. Summaries by geography

4a. Beneficiaries by state

 

4b. Number of schools by state

A total of 2,229 schools have been reached by UNICEF; 44% are from Miranda and Zulia alone.

 

4c. Scatterplot of municipalities

logarithmic scale; larger points indicate more beneficiaries reached, darker blues indicate more activity types

mouse over municipalities to see beneficiaries and distinct activities

A total of 110 municipalities were reached by the UNICEF Education programme.

 

4d. Top 10 municipalities by reach and coverage

by beneficiaries
estado municipio beneficiarios
DISTRITO CAPITAL LIBERTADOR 80482
MIRANDA SUCRE 59176
ZULIA MARACAIBO 55370
BOLIVAR CARONI 37908
ZULIA SAN FRANCISCO 29369
AMAZONAS ATURES 22430
LARA IRIBARREN 21977
BOLIVAR HERES 18293
DELTA AMACURO TUCUPITA 17953
BOLIVAR CEDENO 15681
by coverage
estado municipio coverage_percent
TACHIRA FERNANDEZ FEO 87
TACHIRA AYACUCHO 79
ZULIA MACHIQUES DE PERIJA 79
AMAZONAS AUTONOMO AUTANA 76
TACHIRA SAMUEL DARIO MALDONADO 75
TACHIRA PANAMERICANO 72
MIRANDA PLAZA 68
TACHIRA INDEPENDENCIA 68
TACHIRA JUNIN 65
MIRANDA EL HATILLO 64

Together, the 10 municipalities with the highest reach (above left) form 49% of the 728,408 beneficiaries reached. The average coverage of the school-age population in the municipalities where UNICEF is present is 20%. Coverage refers to the percentage of enrolled children (aged 3-17 years) reached by UNICEF.

 

4e. Histogram of Coverage

Below is a histogram of munciipalities where UNICEF is present showing the coverage of enrolled children (aged 3-17). Of note, we have reached 10% or less of the population in 55 out of the 110 in which we operate. This is in addition to the 226 where no UNICEF Education activities have occurred.

 

5. Reports about partners

5a. Summary by partner

 

5b. Number of activity types implemented by each partner

partner SOCIO 2 SOCIO 1 SOCIO 4 SOCIO 5 UNICEF SOCIO 3 SOCIO 6 SOCIO 7 SOCIO 10 SOCIO 8
act_types 9 8 8 6 6 4 2 2 1 1

 

5c. Partners’ progress over time

mouse over for details

 

5d. Summary table of partners’ achievements

organizacion_implementadora beneficiarios percent_of_total male female sex_ratio municipalities
UNICEF 353,944 38.21 168,281 185,664 0.91 74
SOCIO 1 160,260 17.3 79,958 80,302 1 92
SOCIO 2 145,997 15.76 65,390 80,607 0.81 51
SOCIO 5 113,845 12.29 50,511 63,334 0.8 10
SOCIO 4 86,074 9.29 42,534 43,540 0.98 17
SOCIO 7 31,322 3.38 14,750 16,572 0.89 10
SOCIO 8 29,471 3.18 15,379 14,092 1.09 17
SOCIO 10 2,461 0.27 1,151 1,310 0.88 1
SOCIO 3 2,423 0.26 862 1,561 0.55 3
SOCIO 6 572 0.06 5 23 0.22 7

 

6. Maps and reference table

 

6a. Maps at municipal level

 

6b. Reference table - municipal level

use UNICEF_present to filter to municipalities where the Education programme operates

CA01.05 Promocion de mensajes claves para la comunidad escolar is not included

LS0tDQp0aXRsZTogIkNsZWFuaW5nIGFuZCBSZXBvcnRpbmcgb24gRWR1Y2F0aW9uIDVXIGRhdGEgZnJvbSBWZW5lenVlbGEiDQphdXRob3I6ICJTZWFuIE5nIg0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQ9JyVkICVCLCAlWScpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlDQogICAgY29sbGFwc2VkOiBmYWxzZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0aGVtZTogcmVhZGFibGUNCi0tLQ0KDQojIEEuIENsZWFuaW5nIHRoZSA1VyBkYXRhDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoID0gOS41KQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkoc3RyaW5naSkNCmxpYnJhcnkocGFuZGVyKQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KGZvcmNhdHMpDQpsaWJyYXJ5KGphbml0b3IpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoZ2dtYXApDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShwYXRjaHdvcmspDQpsaWJyYXJ5KG1hcHRvb2xzKQ0KbGlicmFyeShnZ2ZvcmNlKQ0KbGlicmFyeShnZ3RoZW1lcykNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShrYWJsZUV4dHJhKQ0KbGlicmFyeShEVCkNCmxpYnJhcnkodGlueXRleCkNCg0KIyB0YWJsZXMgYWxsIGluIG9uZSByb3cNCnBhbmRlck9wdGlvbnMoJ3RhYmxlLnNwbGl0LnRhYmxlJywgSW5mKQ0KDQojIHRob3VzYW5kcyBzZXBhcmF0b3INCnBhbmRlck9wdGlvbnMoImJpZy5tYXJrIiwgIiwiKQ0KDQpgYGANCg0KJm5ic3A7DQoNCj4gVGhpcyBmaXJzdCBzZWN0aW9uIGRldGFpbHMgYW4gZXhhbXBsZSBvZiB0aGUgY29kZSBuZWNlc3NhcnkgZm9yIGNsZWFuaW5nIGEgNVcgZGF0YXNldCBpbiBSLiA1VyBkYXRhIGlzIHR5cGljYWxseSBtZXNzeSBhbmQgaW4gd2lkZSBmb3JtYXQuIEFkZGl0aW9uYWxseSwgZGF0YSB3cmFuZ2xpbmcgaXMgdGltZSBjb25zdW1pbmcgYW5kIGFuIGluZWZmaWNpZW50IHVzZSBvZiBhIHNwZWNpYWxpc3QncyB0aW1lLiBUaGUgY29kZSBwcmVzZW50ZWQgYmVsb3cgaW50ZW5kcyB0byBkZW1vbnN0cmF0ZSB0aGF0IHRoaXMgbW9udGhseSAob3IgbW9yZSBmcmVxdWVudCkgb2NjdXJlbmNlIGNhbiBiZSBncmVhdGx5IGF1dG9tYXRlZCwgYWxsb3dpbmcgZm9yIG1vcmUgdGltZWx5IGFuZCBhY2N1cmF0ZSBhbmFseXNpcyBhcyB3ZWxsIGFzIGNyZWF0aW5nIHRoZSBzcGFjZSBmb3IgbW9yZSB0YWlsb3JlZCByZXBvcnRpbmcuICANCg0KJm5ic3A7DQoNCiMjIDEuIFJlYWRpbmcgaW4gdGhlIGRhdGFzZXQNCg0KYGBge3IgcmVhZGluZy1pbi14bHN4LCBlY2hvPVRSVUV9DQojIHNwZWNpZnlpbmcgY29sdW1uIHR5cGVzIA0KYWN0X2NvbF90eXBlcyA8LSBjKCJkYXRlIiwgImRhdGUiLCAidGV4dCIsICJ0ZXh0IiwidGV4dCIsInRleHQiLA0KICAgICAgICAgICAgICAgICAgICJ0ZXh0IiwidGV4dCIsInRleHQiLCJ0ZXh0IiwidGV4dCIsInRleHQiLCJ0ZXh0IiwNCiAgICAgICAgICAgICAgICAgICAibnVtZXJpYyIsICJudW1lcmljIiwgInRleHQiLCJ0ZXh0IiwidGV4dCIsDQogICAgICAgICAgICAgICAgICAgInRleHQiLCJ0ZXh0IiwidGV4dCIsICJudW1lcmljIiwgInRleHQiLCANCiAgICAgICAgICAgICAgICAgICAiZGF0ZSIsICJkYXRlIiwgInRleHQiLCAibnVtZXJpYyIsICJudW1lcmljIiwNCiAgICAgICAgICAgICAgICAgICAibG9naWNhbCIsICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsDQogICAgICAgICAgICAgICAgICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLA0KICAgICAgICAgICAgICAgICAgICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwNCiAgICAgICAgICAgICAgICAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiKQ0KDQojIHlvdSdyZSBnb25uYSBoYXZlIHRvIGxpdmUgd2l0aCB0aGUgZXJyb3IgbWVzc2FnZXMsDQojIHNpbmNlIHlvdSBjYW4ndCBzbGljZSBiZWZvcmUgcmVhZF9leGNlbCgpIGFyZ3VtZW50DQoNCmFjdDE8LSByZWFkX2V4Y2VsKCJkYXRhYmFzZSBhY3Rpdml0aWVzIDVXLnhsc3giLCANCiAgICAgICAgICAgICAgICAgICAgIHNoZWV0ID0gImRhdGEiLCANCiAgICAgICAgICAgICAgICAgICAgIHNraXAgPSAxLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGFjdF9jb2xfdHlwZXMpICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUgDQogIHJlbW92ZV9lbXB0eSgpICU+JSANCiAgc2xpY2UoLWMoMSkpICU+JSAjIHJlbW92ZXMgdGhlIHNlY29uZCByb3cNCiAgc2xpY2UoLWMoMTIwNTUpKSAjIHJlbW92ZXMgdGhlIGdyYW5kIHRvdGFsDQoNCmBgYA0KJm5ic3A7DQoNCiMjIDIuIFN0cmluZyBNYW5pcHVsYXRpb24gYW5kIFJlY29kaW5nIA0KDQojIyMgMmEuIFJlbmFtaW5nIENvbHVtbnMgDQoNCj4gSW5zdGVhZCBvZiBzaG93aW5nIGEgbG9uZyB2ZWN0b3Igb2YgY29sdW1uIG5hbWVzLCBoZXJlIGlzIGEgYGdsaW1wc2UoKWAgb2YgdGhlIHJlbmFtZWQgZGF0YXNldDogDQoNCmBgYHtyfQ0KYWN0X25hbWVzIDwtIGMoImZlY2hhX3JlcG9ydGFkb19jbHVzdGVyIiwNCiAgICAgICAgICAgICAgICJtZXNfcmVwb3J0YWRvIiwNCiAgICAgICAgICAgICAgICJjb2RpZ29fZGVfcHJveWVjdG8iLA0KICAgICAgICAgICAgICAgIm5vbWJyZV9kZWxfcHJveWVjdG8iLA0KICAgICAgICAgICAgICAgIm9yZ2FuaXphY2lvbl9saWRlciIsDQogICAgICAgICAgICAgICAib3JnYW5pemFjaW9uX2ltcGxlbWVudGFkb3JhIiwNCiAgICAgICAgICAgICAgICJlc3RhZG8iLA0KICAgICAgICAgICAgICAgInBjb2RlMSIsDQogICAgICAgICAgICAgICAibXVuaWNpcGlvIiwNCiAgICAgICAgICAgICAgICJwY29kZTIiLA0KICAgICAgICAgICAgICAgInBhcnJvcXVpYSIsDQogICAgICAgICAgICAgICAicGNvZGUzIiwNCiAgICAgICAgICAgICAgICJ1YmljYWNpb24iLA0KICAgICAgICAgICAgICAgImxhdGl0dWQiLA0KICAgICAgICAgICAgICAgImxvbmdpdHVkIiwNCiAgICAgICAgICAgICAgICJhY3RpdmlkYWRfZnVsbCIsDQogICAgICAgICAgICAgICAiYWN0aXZpZGFkX2NvZGlnbyIsDQogICAgICAgICAgICAgICAiYWN0aXZpZGFkX2Rlc2MiLA0KICAgICAgICAgICAgICAgImFjdGl2aWRhZF9jb2RpZ29fZGVzYyIsDQogICAgICAgICAgICAgICAiYWN0X2NvdmlkIiwNCiAgICAgICAgICAgICAgICJ1bmlkYWQiLA0KICAgICAgICAgICAgICAgImNhbnRpZGFkX2RlbF9tZXMiLA0KICAgICAgICAgICAgICAgInJlY3VycmVudGVfYmVuZWZpY2lhcmlvcyIsDQogICAgICAgICAgICAgICAiZmVjaGFfZGVfaW5pY2lvIiwNCiAgICAgICAgICAgICAgICJmZWNoYV9wcmV2aXN0YV9maW5hbGl6YWNpb24iLA0KICAgICAgICAgICAgICAgImVzdGF0dXNfYWN0aXZpZGFkIiwNCiAgICAgICAgICAgICAgICJ0b3RhbF9iZW5lZmljaWFyaW9zIiwNCiAgICAgICAgICAgICAgICJjaGVja19iZW5lZmljaWFyaWVzIiwNCiAgICAgICAgICAgICAgICJ0X2ZfYmVuIiwNCiAgICAgICAgICAgICAgICJwZXJjZW50X3BvYmxhY2lvbl9pbmRpZ2VuYSIsDQogICAgICAgICAgICAgICAicGVyY2VudF9wZXJzb25hc19jb25fZGlzY2FwYWNpZGFkIiwNCiAgICAgICAgICAgICAgICJtXzBfMyIsDQogICAgICAgICAgICAgICAibV8zXzYiLA0KICAgICAgICAgICAgICAgIm1fN18xMiIsDQogICAgICAgICAgICAgICAibV8xMl8xNyIsDQogICAgICAgICAgICAgICAibV8xOF8xOSIsDQogICAgICAgICAgICAgICAiZl8wXzMiLA0KICAgICAgICAgICAgICAgImZfM182IiwNCiAgICAgICAgICAgICAgICJmXzdfMTIiLA0KICAgICAgICAgICAgICAgImZfMTJfMTciLA0KICAgICAgICAgICAgICAgImZfMThfMTkiLA0KICAgICAgICAgICAgICAgImZfbWF5b3Jlc19kZV8xOSIsDQogICAgICAgICAgICAgICAibV9tYXlvcmVzX2RlXzE5IikNCg0KIyByZW5hbWVkIA0KbmFtZXMoYWN0MSkgPC0gYWN0X25hbWVzDQoNCmdsaW1wc2UoYWN0MSkNCmBgYA0KDQojIyMgMmIuIFJlbW92aW5nIGFjY2VudHMgYW5kIHN0YW5kYXJkaXNpbmcgY2FzZQ0KDQpgYGB7ciByZW1vdmUtYWNjZW50cywgZWNobz1UUlVFfQ0KIyBmdW5jdGlvbiB0byByZW1vdmUgYWNjZW50cw0Kcm1fYWNjZW50IDwtIGZ1bmN0aW9uKGNvbG5zKXsNCiAgY29sbnMgPC0gc3RyaV90cmFuc19nZW5lcmFsKGNvbG5zLCAiTGF0aW4tQVNDSUkiKQ0KfQ0KDQojIHJlbW92aW5nIGFjY2VudHMNCmFjdDEgPC0gYWN0MSAlPiUgDQogIG11dGF0ZShlc3RhZG8gICAgPSBybV9hY2NlbnQoc3RyX3RvX3VwcGVyKGVzdGFkbykpLCAjIHN0cmluZyB0byB1cHBlciBhbmQgcm1fYWNjZW50DQogICAgICAgICBtdW5pY2lwaW8gPSBybV9hY2NlbnQoc3RyX3RvX3VwcGVyKG11bmljaXBpbykpLA0KICAgICAgICAgcGFycm9xdWlhID0gcm1fYWNjZW50KHN0cl90b191cHBlcihwYXJyb3F1aWEpKSwNCiAgICAgICAgIHViaWNhY2lvbiA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIodWJpY2FjaW9uKSksDQogICAgICAgICBhY3RpdmlkYWRfZGVzYyA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIoYWN0aXZpZGFkX2Rlc2MpKSkNCg0KYGBgDQoNCiMjIyAyYy4gUmVjb2RpbmcgZXJyb25lb3VzIGRhdGENCg0KPiBBbmQgbXV0YXRpbmcgYSBuZXcgZGF0ZSBjb2x1bW4ganVzdCB3aXRoIHRoZSBtb250aA0KDQpgYGB7ciByZWNvZGluZywgZWNobz1UUlVFfQ0KIyByZWNvZGluZyANCmFjdDEgPC0gYWN0MSAlPiUgDQogIG11dGF0ZShyZWN1cnJlbnRlX2JlbmVmaWNpYXJpb3MgPSANCiAgICAgICAgICAgcmVjb2RlKHJlY3VycmVudGVfYmVuZWZpY2lhcmlvcywgDQogICAgICAgICAgICAibm8iID0gRkFMU0UsICJObyIgPSBGQUxTRSwgIlNpIiA9IFRSVUUsICJzaSIgPSBUUlVFLCAic8OtIiA9IFRSVUUsICJTw60iID0gVFJVRSksDQogICAgICAgICBhY3RfY292aWQgPSByZWNvZGUoYWN0X2NvdmlkLCANCiAgICAgICAgICAgICJubyIgPSBGQUxTRSwgIk5vIiA9IEZBTFNFLCAiU2kiID0gVFJVRSwgInNpIiA9IFRSVUUsICJzw60iID0gVFJVRSwgIlPDrSIgPSBUUlVFKSkgJT4lIA0KICByZXBsYWNlX25hKGxpc3QocmVjdXJyZW50ZV9iZW5lZmljaWFyaW9zID0gRkFMU0UsIGFjdF9jb3ZpZCA9IEZBTFNFKSkgDQoNCiMgcmVjb2RpbmcgZXN0YXR1c19hY3RpdmlkYWQNCmFjdDEkZXN0YXR1c19hY3RpdmlkYWQgPC0gYWN0MSRlc3RhdHVzX2FjdGl2aWRhZCAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbChjKCJFbiBlamVjdWNpb24iID0gImVqZWN1Y2lvbiIsIA0KICAgICAgICAgICAgICAgICAgICAiZW4gZWplY3VjacOzbiIgPSAiZWplY3VjaW9uIiwgDQogICAgICAgICAgICAgICAgICAgICJlbiBFamVjdWNpw7NuIiA9ICJlamVjdWNpb24iLA0KICAgICAgICAgICAgICAgICAgICAiRW4gZWplY3VjacOzbiIgPSAiZWplY3VjaW9uIiwNCiAgICAgICAgICAgICAgICAgICAgIkVuIEVqZWN1Y2nDs24iID0gImVqZWN1Y2lvbiIsDQogICAgICAgICAgICAgICAgICAgICJmaW5hbGl6YWRhIiA9ICJmaW5hbGl6YWRhIiwNCiAgICAgICAgICAgICAgICAgICAgIkZpbmFsaXphZGEiID0gImZpbmFsaXphZGEiKSkNCg0KIyBjcmVhdGUgYSBuZXcgdmFyaWFibGUgb2YgbGFzdCBkYXkgb2YgbW9udGggb25seSANCmFjdDEkbWVzX3NvbG8gPC0gY2VpbGluZ19kYXRlKGFjdDEkbWVzX3JlcG9ydGFkbywgIm1vbnRoIikgLSBkYXlzKDEpDQpgYGANCg0KJm5ic3A7DQoNCiMjIDMuIENsZWFuaW5nIGxvY2F0aW9ucyANCg0KIyMjIDNhLiBSZWFkIGluIGBsb2NhdGlvbnMuY3N2YA0KDQo+IEFuZCBjaGVjayBpZiB5b3UgbmVlZCB0byB1cGRhdGUgaXQNCg0KYGBge3IgcmVhZC1sb2NhdGlvbnMsIGVjaG89VFJVRX0NCmxvY2F0aW9ucyA8LSByZWFkX2NzdigibG9jYXRpb25zLmNzdiIpICU+JQ0KICBtdXRhdGUoZXN0YWRvICAgID0gcm1fYWNjZW50KHN0cl90b191cHBlcihlc3RhZG8pKSwNCiAgICAgICAgIG11bmljaXBpbyA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIobXVuaWNpcGlvKSksDQogICAgICAgICBwYXJyb3F1aWEgPSBybV9hY2NlbnQoc3RyX3RvX3VwcGVyKHBhcnJvcXVpYSkpLA0KICAgICAgICAgdWJpY2FjaW9uID0gcm1fYWNjZW50KHN0cl90b191cHBlcih1YmljYWNpb24pKSkNCmBgYA0KDQpgYGB7ciwgbG9jYXRpb25zLWNoZWNrLCBlY2hvPVRSVUV9DQojIHNlZSBpZiB5b3UgbmVlZCB0byB1cGRhdGUgbG9jYXRpb25zIA0KIGxvY2F0aW9uc19hZGQgPC0gYWN0MSAlPiUgDQogICBzZWxlY3QoZXN0YWRvLCBwY29kZTEsIG11bmljaXBpbywgcGNvZGUyLCBwYXJyb3F1aWEsIHBjb2RlMywgdWJpY2FjaW9uKSAlPiUgDQogICBkaXN0aW5jdCgpICU+JSANCiAgIGFudGlfam9pbihsb2NhdGlvbnMsIGJ5ID0gInViaWNhY2lvbiIpDQpgYGANCg0KDQojIyMgM2IuIFNwbGl0dGluZyB0aGUgZGF0YXNldCBpbnRvIGNsZWFuIGFuZCBkaXJ0eQ0KPiBUaGlzIHNlY3Rpb24gcmVhZHMgaW4gdGhlIGxvY2F0aW9ucyByZWZlcmVuY2UgZGF0YXNldCB0aGVuIHVzZXMgaXQgdG8gY2xlYW4gYGFkbV9kaXJ0eWAgYW5kIHJld3JpdGVzIGl0IHRvIGBhZG1fZGlydHkxYC4gVGhlIGBkaXN0aW5jdCgpYCBjYWxsIGF0IHRoZSBlbmQgaXMgdG8gZW5zdXJlIHRoYXQgbm8gZHVwbGljYXRlcyBhcmUgaW5jbHVkZWQgYXMgdGhlIGBsZWZ0X2pvaW4oKWAgYXJndW1lbnQgd2lsbCBwcm9kdWN0IGR1cGxpY2F0ZXMuIEFmdGVyIHdoaWNoLCBgYWRtX2NsZWFuYCBhbmQgYGFkbV9kaXJ0eTFgIGFyZSBjb21iaW5lZCBpbnRvIGBhY3QyYC4gDQoNCj4gQXMgYSBub3RlLCB0aGVyZSBpcyBhIHRvIGluY2x1ZGUgYSBzZXQgb2YgbmV3IHBjb2RlcyAtLSAidG9kbyBtdW5pY2lwaW8iIGFuZCAgInRvZG8gZXN0YWRvIi4gDQoNCmBgYHtyIHNwbGl0LWNsZWFuLWRpcnR5LCBlY2hvPVRSVUV9DQojIHNwbGl0dGluZyBpbnRvIHR3byBkYXRhc2V0cywgb25lIGNsZWFuIG9uZSBkaXJ0eS4gDQphZG1fZGlydHkgPC0gYWN0MSAlPiUgDQogIGZpbHRlcihpcy5uYShlc3RhZG8pIHwgaXMubmEocGNvZGUxKSB8DQogICAgICAgICBpcy5uYShtdW5pY2lwaW8pIHwgaXMubmEocGNvZGUyKSB8DQogICAgICAgICBpcy5uYShwYXJyb3F1aWEpIHwgaXMubmEocGNvZGUzKSkNCg0KYWRtX2NsZWFuIDwtIGFjdDEgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKGVzdGFkbykgJiAhaXMubmEocGNvZGUxKSAmDQogICAgICAgICAhaXMubmEobXVuaWNpcGlvKSAmICFpcy5uYShwY29kZTIpICYNCiAgICAgICAgICFpcy5uYShwYXJyb3F1aWEpICYgIWlzLm5hKHBjb2RlMykpIA0KDQpgYGANCg0KIyMjIDNjLiBGaWxsIGluIG1pc3NpbmcgdmFsdWVzIHdpdGggYGNvYWxlc2NlKClgDQoNCmBgYHtyIGZpbGwgaW4gbWlzc2luZyB2YWx1ZXMsIGVjaG89VFJVRX0NCiMgZmlsbGluZyBpbiBtaXNzaW5nIHZhbHVlcw0KYWRtX2RpcnR5IDwtIGFkbV9kaXJ0eSAlPiUgDQogIGxlZnRfam9pbihsb2NhdGlvbnMsIGJ5ID0gInViaWNhY2lvbiIpICU+JSANCiAgbXV0YXRlKGVzdGFkbyAgICA9IGNvYWxlc2NlKGVzdGFkby54LCBlc3RhZG8ueSksDQogICAgICAgICBwY29kZTEgICAgPSBjb2FsZXNjZShwY29kZTEueCwgcGNvZGUxLnkpLA0KICAgICAgICAgbXVuaWNpcGlvID0gY29hbGVzY2UobXVuaWNpcGlvLngsIG11bmljaXBpby55KSwNCiAgICAgICAgIHBjb2RlMiAgICA9IGNvYWxlc2NlKHBjb2RlMi54LCBwY29kZTIueSksDQogICAgICAgICBwYXJyb3F1aWEgPSBjb2FsZXNjZShwYXJyb3F1aWEueCwgcGFycm9xdWlhLnkpLA0KICAgICAgICAgcGNvZGUzICAgID0gY29hbGVzY2UocGNvZGUzLngsIHBjb2RlMy55KSkgJT4lIA0KICBzZWxlY3QoLWVzdGFkby54LCAtZXN0YWRvLnksIC1wY29kZTEueCwgLXBjb2RlMS55LA0KICAgICAgICAgLW11bmljaXBpby54LCAtbXVuaWNpcGlvLnksIC1wY29kZTIueCwgLXBjb2RlMi55LA0KICAgICAgICAgLXBhcnJvcXVpYS54LCAtcGFycm9xdWlhLnksIC1wY29kZTMueCwgLXBjb2RlMy55KSAlPiUgDQogIGRpc3RpbmN0KCkgIyByZW1vdmluZyBkdXBsaWNhdGUgcm93cyBmcm9tIHRoZSBqb2luIA0KDQojIGJpbmRfcm93cygpIGRvZXMgbm90IGNhcmUgYWJvdXQgY29sdW1uIHNlcXVlbmNlIA0KIyBidXQgcHV0IGFkbV9jbGVhbiBmaXJzdCBzbyB0aGF0IHRoZSBvcmlnaW5hbCBvcmRlciBpcyBwcmVzZXJ2ZWQNCmFjdDIgPC0gYmluZF9yb3dzKGFkbV9jbGVhbiwgYWRtX2RpcnR5KQ0KDQpgYGANCg0KIyMjIDNkLiBFcnJvciBjaGVja2luZyB0aGUgam9pbg0KPiBwcmludGluZyB0b3RhbCBiZW5lZmljaWFyaWVzIGZvciBgYWN0MWAgYW5kIGBhY3QyYCwgZm9sbG93ZWQgYnkgYG5yb3coKWAgZm9yIGJvdGguIA0KDQpgYGB7ciBqb2luLWVycm9yLWNoZWNrfQ0KIyBlcnJvciBjaGVja2luZw0Kc3VtKGFjdDEkdG90YWxfYmVuZWZpY2lhcmlvcywgbmEucm0gPSBUUlVFKQ0Kc3VtKGFjdDIkdG90YWxfYmVuZWZpY2lhcmlvcywgbmEucm0gPSBUUlVFKQ0KbnJvdyhhY3QxKQ0KbnJvdyhhY3QyKQ0KYGBgDQoNCiZuYnNwOw0KDQojIyA0LiBCZW5lZmljaWFyeSBkaXNhZ2dyZWdhdGlvbiANCj4gVGhpcyBpcyB0byBjaGVjayB0aGF0IGB0b3RhbF9iZW5lZmljaWFyaW9zYCBpcyBlcXVhbCB0byB0aGUgc3VtIG9mIGFsbCBkaXNhZ2dyZWdhdGVkIGNvbHVtbnMuIEZpcnN0LCB3ZSBtdXRhdGUgYSBuZXcgY29sdW1uIGJ5IHN1bW1pbmcgYWxsIHRoZSBkaXNhZ2dyZWdhdGVkIGJlbmVmaWNpYXJpZXMgYW5kIGNhbGxpbmcgaXQgYHRvdGFsX2Jlbl9jaGVja2AuIFRoZSBuZXh0IGZ1bmN0aW9uIHByaW50cyB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgdG90YWxfYmVuX2NoZWNrYCBhbmQgYHRvdGFsX2JlbmVmaWNpYXJpb3NgLiBGaW5hbGx5LCB3ZSBtdXRhdGUgYSBuZXcgY29sdW1uIGluIHRoZSBkYXRhc2V0IGNhbGxlZCBgbm9fZXNwX2JlbmAgb3IgYmVuZWZpY2lhcmlvcyBubyBlc3BlY2lmaWNhZG9zIHRvIGNvbGxlY3QgdGhlIGRpZmZlcmVuY2VzIGFuZCBlbnN1cmUgdGhhdCB3ZSBkbyBub3QgbG9zZSB0aGVtLiANCg0KYGBge3IgYmVuY2hlY2stYW5kLW5vLWVzcC1iZW4sIGVjaG89VFJVRSB9DQojIG11dGF0aW5nIGJlbmNoZWNrIGFuZCB1bnNwZWNpZmllZCBiZW5lZmljaWFyaWVzIGNvbHVtbnMgDQphY3QyIDwtIGFjdDIgJT4lIA0KICBtdXRhdGUodG90YWxfYmVuX2NoZWNrID0gc2VsZWN0KC4sIG1fMF8zOm1fbWF5b3Jlc19kZV8xOSkgJT4lICByb3dTdW1zKG5hLnJtID0gVFJVRSksIA0KICAgICAgICAgbm9fZXNwX2JlbiAgICAgID0gcm91bmQodG90YWxfYmVuZWZpY2lhcmlvcykgLSByb3VuZCh0b3RhbF9iZW5fY2hlY2spKSANCg0KYGBgDQoNCj4gTmV4dCwgd2UgcHJpbnQgcm93cyB3aGVyZSB0aGUgc3VtIG9mIGRpc2FnZ3JlZ2F0ZWQgYmVuZWZpY2lhcmllcyBkbyBub3QgbWF0Y2ggdGhlIHRvdGFscyByZXBvcnRlZCBpbiB0aGUgYHRvdGFsX2JlbmVmaWNpYXJpb3NgIGNvbHVtbi4gDQoNCmBgYHtyIHByaW50aW5nLWJlbmNoZWNrfQ0KIyBwcmludGluZyB0aGUgYmVuY2hlY2sNCiMgdGhlIHJvdW5kIGlzIG5lY2Vzc2FyeSBkdWUgdG8gZmxvYXRpbmcgcG9pbnQgYXJpdGhtZXRpYyBhcyBzb21lIHZhbHVlcyBhcmUNCiMgY2xvc2UgZW5vdWdoIHRvIDAgdG8gYmUgaWdub3JlZCBieSB1cyBidXQgbm90IGJ5IFIuIA0KIyBvbmx5IHBhbmRlcigpIGlmIHlvdSB3YW50IHRvIHJlYWQgdGhlIGh0bWwNCm5vX2VzcCA8LSBhY3QyICU+JSANCiAgZmlsdGVyKHJvdW5kKHRvdGFsX2JlbmVmaWNpYXJpb3MpICE9IHJvdW5kKHRvdGFsX2Jlbl9jaGVjaykpICU+JSANCiAgc2VsZWN0KG9yZ2FuaXphY2lvbl9pbXBsZW1lbnRhZG9yYSwgYWN0aXZpZGFkX2Rlc2MsIA0KICAgICAgICAgdWJpY2FjaW9uLCB0b3RhbF9iZW5fY2hlY2ssIHRvdGFsX2JlbmVmaWNpYXJpb3MsIG5vX2VzcF9iZW4pDQoNCmthYmxlKG5vX2VzcCwgY2FwdGlvbiA9ICJVbmRpc2FnZ3JlZ2F0ZWQgYmVuZWZpY2lhcmllcyIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gImJvcmRlcmVkIiwgZm9udF9zaXplID0gMTIpDQpgYGANCg0KJm5ic3A7DQoNCiMjIDUuIE91dHB1dHMNCg0KIyMjIDVhLiBDbGVhbmVkIHdpZGUgdmVyc2lvbg0KYGBge3IgZGF0ZXN0YW1wLCBlY2hvPVRSVUV9DQojIHRpbWVzdGFtcCBmb3IgYWxsIHRoZSBmaWxlcyB0byBiZSB3cml0dGVuIGJlbG93DQpub3cgPC0gU3lzLnRpbWUoKQ0KYGBgDQoNCj4gRm9yIHN1Ym1pc3Npb25zIHRvIE9DSEEsIHRoaXMgb25lIGFsaWducyB3aXRoIHRoZWlyIGZvcm1hdA0KDQpgYGB7ciBjbGVhbmVkLXdpZGUsIGVjaG89VFJVRSwgZXZhbD1GQUxTRX0NCiMgdHVybiBvbiBldmFsIGlmIHlvdSB3YW50IHRoZSBmaWxlDQpmaWxlbmFtZV93aWRlIDwtIHBhc3RlMChmb3JtYXQobm93LCAiJXklbSVkXyVIJU1fIiksICI1V193aWRlLmNzdiIpDQp3cml0ZV9jc3YoYWN0MiwgZmlsZW5hbWVfd2lkZSkNCmBgYA0KDQojIyMgNWIuIFVuaXF1ZSBiZW5lZmljaWFyaWVzDQoNCj4gVGhpcyBzZWN0aW9uIHBpdm90cyB0aGUgZGF0YXNldCBsb25nZXIgaW50byB0aWR5IGRhdGEgd2hpY2gsIHdpdGggb25lIG9ic2VydmF0aW9uIHBlciBpbnN0YW5jZSBvZiBhZ2UgYW5kIHNleDsgdGhpcyBpcyBuZWNlc3NhcnkgZm9yIGVhc3kgcGxvdHRpbmcgYW5kIGFkZGl0aW9uYWwgb3BlcmF0aW9ucy4gQWRkaXRpb25hbGx5LCByb3dzIHdpdGggbm8gYmVuZWZpY2lhcmllcyBhcmUgZmlsdGVyZWQgb3V0LiANCg0KPiBUaGUgZGF0YXNldCBgdV9iZW5gIGlzIGNyZWF0ZWQgYnkgdGFraW5nIHRoZSBoaWdoZXN0IG51bWJlciBvZiBiZW5lZmljaWFyaWVzIGJ5IGFnZSBhbmQgc2V4IGdyb3VwIGJ5IGxvY2F0aW9uLiBUaGUgY29sdW1ucyBhcmUgdGhlbiBmaWx0ZXJlZCBkb3duIHRvIGNyZWF0ZSBhIG1vcmUgdXNhYmxlIGRhdGFzZXQuIFdlIHdpbGwgdXNlIHRoaXMgZGF0YXNldCBmb3IgYW55IG9wZXJhdGlvbnMgcmVsYXRlZCB0byB1bmlxdWUgYmVuZWZpY2lhcmllcyAoaW5kaXZpZHVhbHMpLCBpbmNsdWRpbmcgY29tcGFyaXNvbnMgd2l0aCBjZW5zdXMgZGF0YSB0byBkZXRlcm1pbmUgcmVhY2ggYW5kIGNvdmVyYWdlLiBQbGVhc2Ugbm90ZSB0aGF0IG5vdCBhbGwgYWN0aXZpdGllcyB3aWxsIGJlIHJlcHJlc2VudGVkIGluIHRoaXMgZGF0YXNldCBhcyBvbmx5IHRoZSBtYXggb2YgYmVuZWZpY2lhcmllcyBwZXIgZGlzYWdncmVnYXRpb24gZ3JvdXAgcGVyIGxvY2F0aW9uIHdhcyBzZWxlY3RlZC4gDQoNCmBgYHtyIHVuaXF1ZS1iZW5maWNpYXJpZXMsIGVjaG89VFJVRX0NCiMgcGl2b3RpbmcgbG9uZ2VyIGFuZCBjcmVhdGluZyBuZXcgZGF0YWZyYW1lDQogIA0KdV9iZW4gPC0gYWN0MiAlPiUgDQogIHNlbGVjdCgtdF9mX2JlbiwgLXRvdGFsX2Jlbl9jaGVjaykgJT4lICMgcmVtZW1iZXIgdG8gZHJvcCB0aGVtDQogIHJlbG9jYXRlKG1lc19zb2xvKSAlPiUgIyBtb3ZlcyBtZXNfc29sbyB0byB0aGUgZmlyc3QgdmFyaWFibGUNCiAgcGl2b3RfbG9uZ2VyKG1fMF8zOm5vX2VzcF9iZW4sIA0KICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiZGVzYWdyZWdhY2lvbiIsIHZhbHVlc190byA9ICJiZW5lZmljaWFyaW9zIikgJT4lIA0KICBmaWx0ZXIocmVjdXJyZW50ZV9iZW5lZmljaWFyaW9zID09IEZBTFNFKSAlPiUNCiAgZmlsdGVyKGJlbmVmaWNpYXJpb3MgIT0gMCkgJT4lICMgZW1wdHkgY2VsbHMgYXJlIDAgaW4gdGhlIDVXIHRhYmxlDQogIGdyb3VwX2J5KHViaWNhY2lvbiwgZGVzYWdyZWdhY2lvbikgJT4lIA0KICBzbGljZSh3aGljaC5tYXgoYmVuZWZpY2lhcmlvcykpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgc2VsZWN0KG1lc19zb2xvLCBlc3RhZG8sIHBjb2RlMSwgbXVuaWNpcGlvLCBwY29kZTIscGFycm9xdWlhLCBwY29kZTMsIA0KICAgICAgICAgdWJpY2FjaW9uLCBsYXRpdHVkLCBsb25naXR1ZCwNCiAgICAgICAgIGRlc2FncmVnYWNpb24sIGJlbmVmaWNpYXJpb3MpDQpgYGANCg0KYGBge3Igd3JpdGluZy11LWJlbi1jc3YsIGVjaG89VFJVRSwgZXZhbD1GQUxTRX0NCiMgd3JpdGluZyBjc3Ygb2YgdV9iZW4gd2l0aCBkYXRlc3RhbXANCiMgdHVybiBvbiBldmFsIGlmIHlvdSB3YW50IHRoZSBmaWxlIA0KZmlsZW5hbWVfdV9iZW4gPC0gcGFzdGUwKGZvcm1hdChub3csICIleSVtJWRfJUglTV8iKSwgInVfYmVuLmNzdiIpDQp3cml0ZV9jc3YodV9iZW4sIGZpbGVuYW1lX3VfYmVuKQ0KYGBgDQoNCg0KIyMjIDVjLiBCZW5lZmljaWFyaWVzIGJ5IGFjdGl2aXR5DQoNCj4gVGhlIGRhdGFzZXQgYGFjdF9iZW5gIGlzIGZvciBhY3Rpdml0eSB0b3RhbHMuIE9ubHkgdGhlIHJvd3MgbWFya2VkIGFzIGByZWN1cnJlbnRlX2JlbmVmaWNpYXJpb3MgPT0gRkFMU0VgIGhhdmUgYmVlbiBzZWxlY3RlZC4gVGhlIGZpcnN0IGluc3RhbmNlIG9mIHJlY3VycmluZyBiZW5lZmljaWFpcmVzIGlzIG1hcmtlZCBGQUxTRSwgd2l0aCBhbGwgc3Vic2VxdWVudCBlbnRyaWVzIGJlaW5nIG1hcmtlZCBUUlVFLiBTaW1pbGFyIHRvIGB1X2JlbmAsIGl0IGhhcyBhbHNvIGJlZW4gcGl2b3RlZCBsb25nZXIgaW50byB0aWR5IGRhdGEuIA0KDQo+IFBsZWFzZSBub3QgdGhhdCB3ZSBjYW4gb25seSBhc3N1cmUgdGhhdCB0aGVyZSBubyBkdXBsaWNhdGlvbnMgd2l0aGluIGxvY2F0aW9ucyBhcyBzcGVjaWZpYyBsb2NhdGlvbnMgbWlnaHQgaGF2ZSBiZWVuIHRhcmdldHRlZCBieSBtb3JlIHRoYW4gb25lIGFjdGl2aXR5LiBGb3IgZ2VvZ3JhcGhpYyBvcGVyYXRpb25zLCBwbGVhc2UgdXNlIGB1X2JlbmAuDQoNCmBgYHtyIGJlbmVmaWNpYXJpZXMtYnktYWN0aXZpdHksIGVjaG89VFJVRX0NCiMgVGhpcyBpcyB0aGUgZGF0YXNldCBmb3IgYmVuZWZpY2lhcmllcw0KYWN0X2JlbiA8LSBhY3QyICU+JQ0KICBzZWxlY3QoLXRfZl9iZW4sIC10b3RhbF9iZW5fY2hlY2spICU+JSAjIHJlbWVtYmVyIHRvIGRyb3AgdGhlbQ0KICByZWxvY2F0ZShtZXNfc29sbykgJT4lICMgbW92ZXMgbWVzX3NvbG8gdG8gdGhlIGZpcnN0IHZhcmlhYmxlDQogIGZpbHRlcihyZWN1cnJlbnRlX2JlbmVmaWNpYXJpb3MgPT0gRkFMU0UpICU+JQ0KICBwaXZvdF9sb25nZXIobV8wXzM6bm9fZXNwX2JlbiwgDQogICAgICAgICAgICAgICBuYW1lc190byA9ICJkZXNhZ3JlZ2FjaW9uIiwgdmFsdWVzX3RvID0gImJlbmVmaWNpYXJpb3MiKSAlPiUgDQogIGZpbHRlcihiZW5lZmljaWFyaW9zICE9IDApICU+JSAjIGVtcHR5IGNlbGxzIGFyZSAwIGluIHRoZSA1VyB0YWJsZQ0KICBncm91cF9ieSh1YmljYWNpb24sIGRlc2FncmVnYWNpb24pICU+JSANCiAgc2VsZWN0KG1lc19zb2xvLCBub21icmVfZGVsX3Byb3llY3RvLCBvcmdhbml6YWNpb25faW1wbGVtZW50YWRvcmEsIA0KICAgICAgICAgZXN0YWRvLCBwY29kZTEsIG11bmljaXBpbywgcGNvZGUyLCBwYXJyb3F1aWEsIHBjb2RlMywgDQogICAgICAgICB1YmljYWNpb24sIGxhdGl0dWQsIGxvbmdpdHVkLA0KICAgICAgICAgYWN0aXZpZGFkX2NvZGlnbywgYWN0aXZpZGFkX2Rlc2MsIGFjdF9jb3ZpZCwNCiAgICAgICAgIGRlc2FncmVnYWNpb24sIGJlbmVmaWNpYXJpb3MpDQoNCmBgYA0KDQoNCmBgYHtyIHdyaXRpbmctYWN0LWJlbi1jc3YsIGVjaG89VFJVRSwgZXZhbD1GQUxTRX0NCiMgd3JpdGluZyBjc3YgYWN0X2JlbiB3aXRoIGRhdGVzdGFtcA0KIyB0dXJuIG9uIGV2YWwgaWYgeW91IHdhbnQgdGhlIGZpbGUgDQpmaWxlbmFtZV9hY3RfYmVuIDwtIHBhc3RlMChmb3JtYXQobm93LCAiJXklbSVkXyVIJU1fIiksICJhY3RfYmVuLmNzdiIpDQp3cml0ZV9jc3YoYWN0X2JlbiwgZmlsZW5hbWVfYWN0X2JlbikNCmBgYA0KDQojIyMgNWQuIENvbXBhcmluZyBgdV9iZW5gLCBgYWN0X2JlbmAgYW5kIGRpZmZlcmVuY2UNCg0KYGBge3IgY29tcGFyaW5nfQ0KDQooc3VtKHVfYmVuJGJlbmVmaWNpYXJpb3MpKQ0KKHN1bShhY3RfYmVuJGJlbmVmaWNpYXJpb3MpKQ0KKHN1bShhY3RfYmVuJGJlbmVmaWNpYXJpb3MpIC0gc3VtKHVfYmVuJGJlbmVmaWNpYXJpb3MpKQ0KYGBgDQoNCiZuYnNwOw0KDQojIEIuIFJlcG9ydGluZyBvbiB0aGUgNVcgZGF0YSANCg0KYGBge3IgcmVwb3J0LXNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyByZWFkIGluIGNlbnN1cyByZWZlcmVuY2UgZGF0YXNldA0KY2VuX3JlZiA8LSByZWFkX2V4Y2VsKCJjZW5zdXNfZGF0YV8yMDE5MTEyMi54bHN4Iiwgc2hlZXQgPSAiZGF0YSIpICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUNCiAgc2VsZWN0KGVzdGFkbywgcGNvZGUxLCBtdW5pY2lwaW8sIHBjb2RlMiwgcGFycm9xdWlhLCBwY29kZTMsIGZpZWxkX29mZmljZSwNCiAgICAgICAgIHBvYmxhY2lvbl90b3RhbF8yMDExLCB4XzIwMTlfcG9ibGFjaW9uX3BhcnJvcXVpYWxfdG90YWwsDQogICAgICAgICBoYW1fMjAxOV9hbWJpdG9zX2dlLCBoYW1fMjAxOV94eF9wb2JyZXphX2Vudl9wb3JfcGFycm9xdWlhLCANCiAgICAgICAgIGhhbV8yMDE5X3h4X3BvYmxhY2lvbl9wb2JyZV9wb3JfcGFycm9xdWlhLA0KICAgICAgICAgcG9ibGFjaW9uX2luZmFudGlsX21lbm9yX2RlXzEyX2Fub3MsIHBvYmxhY2lvbl9hZG9sZXNjZW50ZXNfZGVfMTJfYV8xN19hbm9zLA0KICAgICAgICAgcG9ibGFjaW9uX2RlXzE4X2Fub3NfeV9tYXMsIA0KICAgICAgICAgcG9ibGFjaW9uX3VyYmFuYV9wZXJjZW50LCBhcmVhX2ttMiwgZGVuc2lkYWRfcG9ibGFjaW9uYWxfcHBsX2ttMiwNCiAgICAgICAgIG1hdHJpY3VsYV8yMDE3X2VkdWNhY2lvbl9pbmljaWFsLCBtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25fcHJpbWFyaWEsIA0KICAgICAgICAgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX21lZGlhKQ0KDQojIGZpbHRlcmluZyBvdXQgUFJPTU9DSU9OIE1FTlNBSkVTIENMQVZFUyBQQVJBIExBIENPTVVOSURBRCBFU0NPTEFSDQpDQTEwNSA8LSBhY3RfYmVuICU+JSBmaWx0ZXIoYWN0aXZpZGFkX2NvZGlnbyA9PSAiQ0ExLjA1IikNCg0KIyBjcmVhdGluZyBkYXRhc2V0cyB3aXRob3V0IENBMS4wNSBhbmQNCiMgZm9yIGFjdF9iZW4sIHJlY29kaW5nIFVOSUNFRiBhbmQgbXV0YXRpbmcgc2hvcnQgYWN0aXZpdHkgZGVzY3JpcHRpb25zDQphY3RfYmVuMiA8LSBhY3RfYmVuICU+JSANCiAgZmlsdGVyKGFjdGl2aWRhZF9jb2RpZ28gIT0gIkNBMS4wNSIpICU+JSANCiAgbXV0YXRlKG9yZ2FuaXphY2lvbl9pbXBsZW1lbnRhZG9yYSA9IA0KICAgICAgICAgICBzdHJfcmVwbGFjZV9hbGwob3JnYW5pemFjaW9uX2ltcGxlbWVudGFkb3JhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJVTklDRUYgLSBGb25kbyBkZSBsYXMgTmFjaW9uZXMgVW5pZGFzIHBhcmEgbGEgSW5mYW5jaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVOSUNFRiIpKSAlPiUgDQogIG11dGF0ZShhY3RpdmlkYWRfc2hvcnQgPSByZWNvZGUoYWN0aXZpZGFkX2NvZGlnbywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIENBMS4wMSA9ICIxLjAxX3JlaW5zZXJjaW9uIGVkdWNhdGl2YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIENBMS4wMiA9ICIxLjAyX25pdmVsYWNpb24geSBjYXBhY2l0YWNpb24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDQTEuMDMgPSAiMS4wM19raXRzIGVzY29sYXJlcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIENBMS4wNCA9ICIxLjA0X2FsaW1lbnRhY2lvbiBlc2NvbGFyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0ExLjA1ID0gIjEuMDVfcHJvbW9jaW9uIG1lbnNhamVzIGNsYXZlcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIENBMS4wNiA9ICIxLjA2X2Fwb3lvIHBzaWNvZWR1Y2F0aXZvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0ExLjA3ID0gIjEuMDdfYWN0aXZpZGFkZXMgcmVjcmVhdGl2YXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDQTIuMDggPSAiMi4wOF9lZHVjYWNpb24gYSBkaXN0YW5jaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDQTIuMDkgPSAiMi4wOV9mb3JtYWNpb24gZG9jZW50ZXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDQTIuMTAgPSAiMi4xMF9iZWNhcyBkb2NlbnRlcyIpKQ0KICAgICAgICAgICAgICAgICAgICANCnVfYmVuMiA8LSB1X2JlbiAlPiUgZmlsdGVyKCFzdHJfZGV0ZWN0KC4kdWJpY2FjaW9uLCAiXlJBRElPIikpDQpgYGANCg0KJm5ic3A7DQoNCj4gVGhpcyBpcyBhbiBlbnRpcmVseSBhdXRvbWF0ZWQgcmVwb3J0IC0tIGFsbCBjaGFydHMgYW5kIHRhYmxlcywgYXMgd2VsbCBhcyBhbGwgZmlndXJlcyB3aXRoaW4gdGhlIHJlcG9ydCBoYXZlIGJlZW4gZ2VuZXJhdGVkIGZyb20gdGhlIGRhdGEsIHdpdGggbm8gbWFudWFsIGlucHV0LiBUaGlzIHJlcG9ydCBtYWtlcyB1c2Ugb2YgdGhlIG91dHB1dHMgb2YgdGhlIGA1V19jbGVhbmluZ2Agc2VjdGlvbiBhYm92ZS4gVGhpcyBzZXQgb2YgNVcgZGF0YSBwZXJ0YWlucyB0byB0aGUgRWR1Y2F0aW9uIENsdXN0ZXIgaW4gVmVuZXp1ZWxhIGFuZCBoYXMgaGFkIHBhcnRuZXIgaW5mb3JtYXRpb24gcmVtb3ZlZC4gQ29kZSB3aWxsIG5vdCBiZSBzaG93biBpbiB0aGlzIHNlY3Rpb24uICANCg0KJm5ic3A7DQoNCiMjIDEuIFN1bW1hcnkgb2YgYmVuZWZpY2lhcmllcyBieSBhY3Rpdml0eSwgd2l0aCBzZXggcmF0aW8NCg0KYGBge3Igc3VtbWFyeS1UQUJMRS1hY3Rpdml0eS1hbmQtc2V4fQ0KDQojIGFzIGEgbm90ZSwgaSBkb24ndCB0aGluayB5b3UgY2FuIHB1dCBhbiBzdHJfZGV0ZWN0IGluc2lkZSBhIHN1bW1hcmlzZQ0KYWN0X2JlbjIgJT4lIA0KICBtdXRhdGUoc2V4X2JlbiA9IGlmZWxzZShzdHJfZGV0ZWN0KGRlc2FncmVnYWNpb24sICJebSIpLCAibWFsZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShzdHJfZGV0ZWN0KGRlc2FncmVnYWNpb24sICJeZiIpLCAiZmVtYWxlIiwgIm5vX2VzcCIpKSkgJT4lIA0KICBtdXRhdGUoYWN0aXZpZGFkID0gYWN0aXZpZGFkX2Rlc2MpICU+JSANCiAgZ3JvdXBfYnkoYWN0aXZpZGFkKSAlPiUgDQogIHN1bW1hcmlzZSh0b3RhbCA9IHN1bShiZW5lZmljaWFyaW9zLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgbWFsZSA9IHN1bSgoYmVuZWZpY2lhcmlvc1tzZXhfYmVuID09ICJtYWxlIl0pKSwNCiAgICAgICAgICAgIGZlbWFsZSA9IHN1bSgoYmVuZWZpY2lhcmlvc1tzZXhfYmVuID09ICJmZW1hbGUiXSkpLA0KICAgICAgICAgICAgc2V4X3JhdGlvID0gcm91bmQoKG1hbGUvZmVtYWxlKSwgZGlnaXRzID0gMikpICU+JSANCiAgbXV0YXRlKHBlcmNlbnRfb2ZfdG90YWwgPSByb3VuZCgodG90YWwgLyBzdW0odG90YWwpICogMTAwKSwgZGlnaXRzID0gMikpICU+JSANCiAgcmVsb2NhdGUocGVyY2VudF9vZl90b3RhbCwgLmFmdGVyID0gdG90YWwpICU+JSANCiAgYXJyYW5nZShkZXNjKHRvdGFsKSkgJT4lIA0KICBwYW5kZXIoYmlnLm1hcmsgPSAiLCIsIHN0eWxlID0gInJtYXJrZG93biIpDQoNCmBgYA0KDQo+IEEgdG90YWwgb2YgX19gciBmb3JtYXQocm91bmQoc3VtKHVfYmVuMiRiZW5lZmljaWFyaW9zKSksIGJpZy5tYXJrID0gIiwiKWBfXyBpbmRpdmlkdWFscyBoYXZlIGJlZW4gcmVhY2hlZCB0byBkYXRlLiBJbiB0ZXJtcyBvZiBmcmVxdWVuY2llcyAoaW5jbHVzaXZlIG9mIGRvdWJsZSBjb3VudGluZyksIF9fYHIgZm9ybWF0KHN1bShhY3RfYmVuMiRiZW5lZmljaWFyaW9zKSwgYmlnLm1hcmsgPSAiLCIpYF9fIGhhdmUgYmVlbiByZWFjaGVkLiANCg0KPiBBZGRpdGlvbmFsbHksIHRoZSBfX2ByIGZvcm1hdChzdW0oQ0ExMDUkYmVuZWZpY2lhcmlvcyksIGJpZy5tYXJrID0gIiwiKWBfXyBiZW5lZmljaWFyeSBmcmVxdWVuY2llcyByZWFjaGVkIGJ5IHRoZSBhY3Rpdml0eSBQUk9NT0NJT04gTUVOU0FKRVMgQ0xBVkVTIFBBUkEgTEEgQ09NVU5JREFEIEVTQ09MQVIgaGF2ZSBiZWVuIHJlbW92ZWQgZnJvbSB0aGUgdG90YWxzIGluIHRoaXMgcmVwb3J0IGFzIHRoZSBhY3Rpdml0eSBjb25zaXN0cyBvZiBzb2xlbHkgcmFkaW8gbWVzc2FnaW5nLiANCg0KJm5ic3A7DQoNCiMjIDIuIEJlbmVmaWNpYXJpZXMgYnkgYWdlIGdyb3VwDQoqZmlndXJlcyBhcmUgdW5pcXVlIGJlbmVmaWNpYXJpZXMvaW5kaXZpZHVhbHMqDQoNCmBgYHtyIFBMT1QtYmVuZWZpY2lhcmllcy1ieS1hZ2V9DQojIHRvIHJlb3JkZXIgdGhlIHBsb3QNCm9yZHZlYyA8LSBjKCIwLTMiLCAiMy02IiwgIjctMTIiLCAiMTItMTciLCAiMTgtMTkiLCAibWF5b3JfcXVlXzE5IikNCg0KIyBkZiBmb3IgdGhlIHBsb3QNCmFnZV91X2JlbiA8LSB1X2JlbjIgJT4lICMgaW1wb3J0YW50IHRvIHVzZSB1X2JlbiBoZXJlIA0KICBtdXRhdGUoYWdlX2JlbiA9IGNhc2Vfd2hlbigNCiAgICBzdHJfZGV0ZWN0KGRlc2FncmVnYWNpb24sIjBfMyQiKSB+ICIwLTMiLA0KICAgIHN0cl9kZXRlY3QoZGVzYWdyZWdhY2lvbiwiM182JCIpIH4gIjMtNiIsDQogICAgc3RyX2RldGVjdChkZXNhZ3JlZ2FjaW9uLCAiN18xMiQiKSB+ICI3LTEyIiwgDQogICAgc3RyX2RldGVjdChkZXNhZ3JlZ2FjaW9uLCAiMTJfMTckIikgfiAiMTItMTciLA0KICAgIHN0cl9kZXRlY3QoZGVzYWdyZWdhY2lvbiwgIjE4XzE5JCIpIH4gIjE4LTE5IiwNCiAgICBzdHJfZGV0ZWN0KGRlc2FncmVnYWNpb24sICJtYXlvcmVzX2RlXzE5JCIpIH4gIm1heW9yX3F1ZV8xOSIsIA0KICAgIFRSVUUgfiAibm9fZXNwIikpICU+JQ0KICBmaWx0ZXIoYWdlX2JlbiAhPSAibm9fZXNwIikgJT4lIA0KICBncm91cF9ieShhZ2VfYmVuKSAlPiUgDQogIHN1bW1hcmlzZShiZW5lZmljaWFyaW9zID0gc3VtKGJlbmVmaWNpYXJpb3MpKQ0KDQpnZ3Bsb3QoZGF0YSA9IGFnZV91X2JlbiwgYWVzKHggPSBmY3RfcmVvcmRlcihhZ2VfYmVuLCBvcmR2ZWMpLCB5ID0gYmVuZWZpY2lhcmlvcykpICsNCiAgZ2VvbV9jb2woZmlsbCA9ICJjb3JuZmxvd2VyYmx1ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNjYWxlczo6Y29tbWEoYmVuZWZpY2lhcmlvcykpLCB2anVzdCA9IC0wLjI1LCBzaXplID0gNCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJLIiwgc2NhbGUgPSAxZS0zLCBzZXAgPSAiIikpICsNCiAgeGxhYigiR3J1cG9zIHBvciBFZGFkIikgKyB5bGFiKCJCZW5lZmljaWFyaW9zIikgKw0KICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkNCg0KYGBgDQoNCiZuYnNwOw0KDQojIyMgMmEuIEJlbmVmaWNpYXJpZXMgYnkgYWdlIGNvbXBhcmVkIHRvIDIwMTcgRW5yb2xsbWVudA0KDQpgYGB7ciBSRUYtbWF0cmljLWJlbn0NCiMgcmVmZXJlbmNlIGRmIGZvciB0aGUgdGFibGUgYW5kIHRleHQgYmVsb3csIHJlc3RydWN0dXJpbmcgZW5yb2xsbWVudCBkYXRhIGZyb20gY2VuX3JlZg0KbWF0cmljX2JlbiA8LSBjZW5fcmVmICU+JSANCiAgc2VsZWN0KG1hdHJpY3VsYV8yMDE3X2VkdWNhY2lvbl9pbmljaWFsLCBtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25fcHJpbWFyaWEsIA0KICAgICAgICAgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX21lZGlhKSAlPiUNCiAgcmVuYW1lKCIzLTYiID0gbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX2luaWNpYWwsDQogICAgICAgICAiNy0xMiIgPSBtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25fcHJpbWFyaWEsDQogICAgICAgICAiMTItMTciID0gbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX21lZGlhKSAlPiUgDQogIHBpdm90X2xvbmdlcihldmVyeXRoaW5nKCksIG5hbWVzX3RvID0gImFnZV9iZW4iLCB2YWx1ZXNfdG8gPSAibWF0cmljdWxhMjAxNyIsIA0KICAgICAgICAgICAgICAgdmFsdWVzX2Ryb3BfbmEgPSBUUlVFKSAlPiUgDQogIGdyb3VwX2J5KGFnZV9iZW4pICU+JSANCiAgc3VtbWFyaXNlKG1hdHJpY3VsYTIwMTcgPSBzdW0obWF0cmljdWxhMjAxNykpICU+JQ0KICBsZWZ0X2pvaW4oYWdlX3VfYmVuKSAlPiUgDQogIG11dGF0ZShwZXJjZW50X3RvdGFsID0gYmVuZWZpY2lhcmlvcy9tYXRyaWN1bGEyMDE3ICogMTAwKSAlPiUgDQogIHJlbG9jYXRlKGJlbmVmaWNpYXJpb3MsIC5hZnRlciA9IGFnZV9iZW4pICU+JSANCiAgcmVuYW1lKGBFZGFkIGdydXBvYCA9IGFnZV9iZW4pICU+JSANCiAgc2xpY2UoMiwzLDEpICAjIHJlYXJyYW5naW5nIHJvd3MNCiAgDQpgYGANCg0KPiBXaXRoIHJlZmVyZW5jZSB0byB0aGUgMjAxNyBNYXRyaWN1bGEgZGF0YXNldCwgd2UgY2FuIHNlZSB0aGF0IHRoZSBFZHVjYXRpb24gcHJvZ3JhbW1lIGhhcyByZWFjaGVkIGFuIG92ZXJhbGwgYXZlcmFnZSBvZiBfX2ByIHJvdW5kKHN1bShtYXRyaWNfYmVuJGJlbmVmaWNpYXJpb3MpLyhzdW0obWF0cmljX2JlbiRtYXRyaWN1bGEyMDE3KSkqMTAwKWAlX18gb2Ygc2Nob29sZ29pbmcgY2hpbGRyZW4gYWdlZCAzLTE3IG5hdGlvbndpZGUuIENoaWxkcmVuIGFnZWQgMy0xNyBjb25zaXR1dGUgX19gciByb3VuZChzdW0obWF0cmljX2JlbiRiZW5lZmljaWFyaW9zKS8oc3VtKHVfYmVuMiRiZW5lZmljaWFyaW9zKSkqMTAwKWAlX18gb2YgYWxsIFVOSUNFRiBiZW5lZmljaWFyaWVzLiANCg0KYGBge3IgVEFCTEUtbWF0cmljLWJlbn0NCnBhbmRlcihtYXRyaWNfYmVuLCBiaWcubWFyayA9ICIsIiwgc3R5bGUgPSAicm1hcmtkb3duIikNCmBgYA0KDQombmJzcDsNCg0KIyMgMy4gQ2hhbmdlcyBzaW5jZSBwcmV2aW91cyBtb250aA0KDQpgYGB7ciBSRUYtZm9yLXRleHQtY3VtdWxhdGl2ZS1kYXRhc2V0c30NCg0KIyBjcmVhdGluZyByZWZlcmVuY2UgZGZzIGZvciB0aGUgdGV4dCBhbmQgcGxvdCBiZWxvdw0KY3VtX3VfYmVuIDwtIHVfYmVuMiAlPiUgDQogIG11dGF0ZShtZXNfc29sbyA9IGFzLkRhdGUobWVzX3NvbG8pKSAlPiUgDQogIGFycmFuZ2UobWVzX3NvbG8pICU+JSANCiAgZ3JvdXBfYnkobWVzX3NvbG8pICU+JSANCiAgc3VtbWFyaXNlKHN1bV9iZW4gPSBzdW0oYmVuZWZpY2lhcmlvcykpICU+JSANCiAgbXV0YXRlKGN1bXVsYXRpdmUgPSBjdW1zdW0oc3VtX2JlbikpDQoNCmN1bV9hY3RfYmVuIDwtIGFjdF9iZW4yICU+JSANCiAgbXV0YXRlKG1lc19zb2xvID0gYXMuRGF0ZShtZXNfc29sbykpICU+JSANCiAgYXJyYW5nZShtZXNfc29sbykgJT4lIA0KICBncm91cF9ieShtZXNfc29sbykgJT4lIA0KICBzdW1tYXJpc2Uoc3VtX2JlbiA9IHN1bShiZW5lZmljaWFyaW9zKSkgJT4lIA0KICBtdXRhdGUoY3VtdWxhdGl2ZSA9IGN1bXN1bShzdW1fYmVuKSkNCmBgYA0KDQo+IFRoZSBudW1iZXIgb2YgaW5kaXZpZHVhbHMgcmVhY2hlZCBoYXMgaW5jcmVhc2VkIGJ5IF9fYHIgZm9ybWF0KGN1bV91X2JlblsxMSwzXSAtIGN1bV91X2JlblsxMCwzXSwgYmlnLm1hcmsgPSAiLCIpYF9fIGluIHRoZSBwYXN0IG1vbnRoLCByZWFjaGluZyBhIHRvdGFsIG9mIF9fYHIgZm9ybWF0KHJvdW5kKHN1bSh1X2JlbjIkYmVuZWZpY2lhcmlvcykpLCBiaWcubWFyayA9ICIsIilgX18uIFRoZSBudW1iZXIgb2YgYmVuZWZpY2lhcnkgZnJlcXVlbmNpZXMgcmVhY2hlZCBoYXMgaW5jcmVhc2VkIGJ5IF9fYHIgZm9ybWF0KGN1bV9hY3RfYmVuWzExLDNdIC0gY3VtX2FjdF9iZW5bMTAsM10sIGJpZy5tYXJrID0gIiwiKWBfXyBpbiB0aGUgc2FtZSBwZXJpb2QsIHJlYWNoaW5nIGEgdG90YWwgb2YgX19gciBmb3JtYXQoc3VtKGN1bV9hY3RfYmVuWzExLDNdKSwgYmlnLm1hcmsgPSAiLCIpYF9fLg0KDQpgYGB7ciAgbGluZS1QTE9ULWN1bXVsYXRpdmUtYmVuZWZpY2lhcmllc30NCnVfYmVuMiAlPiUgDQogIG11dGF0ZShtZXNfc29sbyA9IGFzLkRhdGUobWVzX3NvbG8pKSAlPiUgDQogIGFycmFuZ2UobWVzX3NvbG8pICU+JSANCiAgZ3JvdXBfYnkobWVzX3NvbG8pICU+JSANCiAgc3VtbWFyaXNlKHN1bV9iZW4gPSBzdW0oYmVuZWZpY2lhcmlvcykpICU+JSANCiAgbXV0YXRlKGN1bXVsYXRpdmUgPSBjdW1zdW0oc3VtX2JlbikpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gbWVzX3NvbG8sIHkgPSBjdW11bGF0aXZlKSkgKw0KICBnZW9tX2xpbmUoKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzY2FsZXM6OmNvbW1hKGN1bXVsYXRpdmUpKSwgdmp1c3QgPSAtMC4yNSwgaGp1c3QgPSAxLCBzaXplID0gMykgKw0KICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJWItJVkiLCBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjp1bml0X2Zvcm1hdCh1bml0ID0gIksiLCBzY2FsZSA9IDFlLTMsIHNlcCA9ICIiKSwNCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLDk1MDAwMCwgYnkgPSAyMDAwMDApKSArICMgd2hhdCBpcyB0aGlzIGJyZWFrcyBkb2luZz8NCiAgeGxhYigiTWVzIFJlcG9ydGFkbyIpICsgeWxhYigiQmVuZWZpY2lhcmlvcyAoY3VtdWxhdGl2bykiKQ0KYGBgDQoNCiZuYnNwOw0KDQojIyMgM2EuIFByb2dyZXNzIGJ5IGFjdGl2aXR5IGJ5IG1vbnRoDQoqbW91c2Ugb3ZlciB0byBzZWUgZGV0YWlscyoNCg0KDQpgYGB7ciBsaW5lLVBMT1RMWS1wcm9ncmVzcy1ieS1hY3Rpdml0eSwgZmlnLndpZHRoPTl9DQphY3RfbGluZXMgPC0gYWN0X2JlbjIgJT4lIA0KICBtdXRhdGUobWVzX3NvbG8gPSBhcy5EYXRlKG1lc19zb2xvKSkgJT4lIA0KICBncm91cF9ieShhY3RpdmlkYWRfc2hvcnQsIG1lc19zb2xvKSAlPiUgDQogIHN1bW1hcmlzZShjdW11bGF0aXZlID0gc3VtKGJlbmVmaWNpYXJpb3MpKSAlPiUgDQogIG11dGF0ZShjdW11bGF0aXZlID0gcm91bmQoY3Vtc3VtKGN1bXVsYXRpdmUpKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBtZXNfc29sbywgeSA9IGN1bXVsYXRpdmUsIGNvbG91ciA9IGFjdGl2aWRhZF9zaG9ydCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAwLjcpICsNCiAgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gIiViLSVZIiwgZGF0ZV9icmVha3MgPSAiMSBtb250aCIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHVuaXRfZm9ybWF0KHVuaXQgPSAiSyIsIHNjYWxlID0gMWUtMywgc2VwID0gIiIpLCANCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCwgNTAwMDAwKSkgKw0KICB4bGFiKCIiKSArIHlsYWIoIkJlbmVmaWNpYXJpb3MiKSArDQogIHNjYWxlX2NvbG91cl9kaXNjcmV0ZShuYW1lID0gIkFjdGl2aWRhZCIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSkgKw0KICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChucm93ID0gMiwgYnlyb3cgPSBUUlVFKSkNCg0KZ2dwbG90bHkoYWN0X2xpbmVzLCB0b29sdGlwID0gYygieCIsICJ5IiwgImNvbG91ciIpKSAlPiUgDQogIGxheW91dChzaG93bGVnZW5kID0gVFJVRSwgbGVnZW5kID0gbGlzdChmb250ID0gbGlzdChzaXplID0gNikpKSAlPiUgDQogICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkNCmBgYA0KPiBQcm9ncmVzcyBpbiByZWNlbnQgbW9udGhzIGhhcyBsYXJnZWx5IGJlZW4gZHVlIHRvIHRoZSBkaXN0cmlidXRpb24gb2YgZWR1Y2F0aW9uIGtpdHMgYW5kIGRpc3RhbmNlIGxlYXJuaW5nLiANCg0KJm5ic3A7DQoNCiMjIDQuIFN1bW1hcmllcyBieSBnZW9ncmFwaHkNCg0KIyMjIDRhLiBCZW5lZmljaWFyaWVzIGJ5IHN0YXRlDQoNCmBgYHtyIFBMT1QtYmVuZWZpY2lhaXJpZXMtYnktc3RhdGV9DQp1X2JlbjIgJT4lIA0KICBncm91cF9ieShlc3RhZG8pICU+JSANCiAgc3VtbWFyaXNlKGJlbmVmaWNpYXJpb3MgPSBzdW0oYmVuZWZpY2lhcmlvcykpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBmY3RfcmVvcmRlcihlc3RhZG8sIGJlbmVmaWNpYXJpb3MsIC5kZXNjID0gVFJVRSksIA0KICAgICAgICAgICAgIHkgPSBiZW5lZmljaWFyaW9zKSkgKw0KICBnZW9tX2NvbChmaWxsID0gImNvcm5mbG93ZXJibHVlIikgKw0KICB5bGltKDAsIDg1MDAwMCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc2NhbGVzOjpjb21tYShiZW5lZmljaWFyaW9zLCBhY2N1cmFjeSA9IDEpKSwgDQogICAgICAgICAgICB2anVzdCA9IC0wLjI1LCBoanVzdCA9IDAuMDUsIHNpemUgPSAzLCBhbmdsZSA9IDMwKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSB1bml0X2Zvcm1hdCh1bml0ID0gIksiLCBzY2FsZSA9IDFlLTMsIHNlcCA9ICIiKSwgDQogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsIDIwMDAwMCkpICsNCiAgeGxhYigiIikgKyB5bGFiKCJCZW5lZmljaWFyaW9zIikgKyANCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCmBgYA0KDQombmJzcDsNCg0KYGBge3IgUkVGLWZvci11YmljYWNpb24tdGV4dH0NCm1pcmFfenVsIDwtIHVfYmVuMiAlPiUgZmlsdGVyKGVzdGFkbyA9PSAiTUlSQU5EQSIgfCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzdGFkbyA9PSAiWlVMSUEiKQ0KYGBgDQoNCiMjIyA0Yi4gTnVtYmVyIG9mIHNjaG9vbHMgYnkgc3RhdGUNCj4gQSB0b3RhbCBvZiBfX2ByIGZvcm1hdChuX2Rpc3RpbmN0KHVfYmVuMiR1YmljYWNpb24pLCBiaWcubWFyayA9ICIsIilgX18gc2Nob29scyBoYXZlIGJlZW4gcmVhY2hlZCBieSBVTklDRUY7IF9fYHIgcm91bmQoKG5fZGlzdGluY3QobWlyYV96dWwkdWJpY2FjaW9uKSkgLyAobl9kaXN0aW5jdCh1X2JlbjIkdWJpY2FjaW9uKSkgKiAxMDApYCVfXyBhcmUgZnJvbSBNaXJhbmRhIGFuZCBadWxpYSBhbG9uZS4gDQoNCmBgYHtyIFBMT1Qtb2YtdWJpY2FjaW9uLWJ5LXN0YXRlfQ0KdV9iZW4yICU+JSANCiAgZ3JvdXBfYnkoZXN0YWRvKSAlPiUgDQogIGRpc3RpbmN0KHViaWNhY2lvbikgJT4lIA0KICBzdW1tYXJpc2UodWJpY2FjaW9uID0gbigpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IGZjdF9yZW9yZGVyKGVzdGFkbywgdWJpY2FjaW9uLCAuZGVzYyA9IFRSVUUpLCB5ID0gdWJpY2FjaW9uKSkgKw0KICBnZW9tX2NvbChmaWxsID0gImNvcm5mbG93ZXJibHVlIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQodWJpY2FjaW9uKSksIHZqdXN0ID0gLTAuMjUsIHNpemUgPSAzKSArIA0KICB4bGFiKCIiKSArIHlsYWIoIk51bWVybyBkZSBFc2N1ZWxhcyIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkNCg0KYGBgDQoNCiZuYnNwOw0KDQpgYGB7ciBSRUYtZm9yLWFsbF9tdW59DQojIGNyZWF0aW5nIHRoZSBhbGxfbXVuIGRmDQojIGFsbF9tdW4gaXMgb25lIG9icyBwZXIgcGNvZGUyDQphbGxfbXVuIDwtIHVfYmVuMiAlPiUgDQogIG11dGF0ZShpc19tYXRyaWMgPSBjYXNlX3doZW4oICMgZm9yIGJlbmVmaWNpYXJpZXMgYWdlZCAzLTE3DQogICAgICAgIHN0cl9kZXRlY3QoZGVzYWdyZWdhY2lvbiwiM182JCIpIH4gIm1hdHJpYyIsDQogICAgICAgIHN0cl9kZXRlY3QoZGVzYWdyZWdhY2lvbiwiN18xMiQiKSB+ICJtYXRyaWMiLA0KICAgICAgICBzdHJfZGV0ZWN0KGRlc2FncmVnYWNpb24sIjEyXzE3JCIpIH4gIm1hdHJpYyIsDQogICAgICAgIFRSVUUgfiAibm9uX21hdHJpYyIpKSAlPiUgDQogIG11dGF0ZShiZW5lZmljaWFyaW9zXzNfMTcgPSBpZmVsc2UoaXNfbWF0cmljID09ICJtYXRyaWMiLCBiZW5lZmljaWFyaW9zLCAwKSkgJT4lIA0KICBncm91cF9ieShlc3RhZG8sIG11bmljaXBpbywgcGNvZGUyKSAlPiUgDQogIHN1bW1hcmlzZShiZW5lZmljaWFyaW9zID0gcm91bmQoc3VtKGJlbmVmaWNpYXJpb3MpKSwNCiAgICAgICAgICAgIGJlbmVmaWNpYXJpb3NfM18xNyA9IHJvdW5kKHN1bShiZW5lZmljaWFyaW9zXzNfMTcpKSkgJT4lDQogIHVuZ3JvdXAoKSAlPiUgDQogIGxlZnRfam9pbihhY3RfYmVuICU+JSAjIGJyaW5naW5nIGFjdGl2aXR5IGNvdW50cyBpbnRvIHVfYmVuDQogICAgICAgICAgICBncm91cF9ieShwY29kZTIpICU+JSANCiAgICAgICAgICAgIHN1bW1hcmlzZShhY3RfdHlwZXMgPSBuX2Rpc3RpbmN0KGFjdGl2aWRhZF9jb2RpZ28pKSkgJT4lIA0KICByaWdodF9qb2luKGNlbl9yZWYgJT4lICMgZm9yIGJyaW5naW5nIG1hdHJpY3VsYTIwMTcgaW50byBhbGxfbXVuDQogICAgICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoIm1hdHJpY3VsYV8yMDE3X2VkdWNhY2lvbl9pbmljaWFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25fcHJpbWFyaWEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25fbWVkaWEiKSwgDQogICAgICAgICAgICAgICAgICAgICBuYW1lc190byA9ICJhZ2VfYmVuIiwgdmFsdWVzX3RvID0gIm1hdHJpY3VsYTIwMTciLCANCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlc19kcm9wX25hID0gVFJVRSkgJT4lIA0KICAgICAgICAgICAgc2VsZWN0KHBjb2RlMiwgYWdlX2JlbiwgbWF0cmljdWxhMjAxNykgJT4lIA0KICAgICAgICAgICAgZ3JvdXBfYnkocGNvZGUyKSAlPiUgDQogICAgICAgICAgICBzdW1tYXJpc2UobWF0cmljdWxhMjAxNyA9IHN1bShtYXRyaWN1bGEyMDE3KSkpICU+JSANCiAgbXV0YXRlKGNvdmVyYWdlX3BlcmNlbnQgPSByb3VuZChiZW5lZmljaWFyaW9zXzNfMTcgLyBtYXRyaWN1bGEyMDE3ICogMTAwKSkgJT4lIA0KICBtdXRhdGUoZXN0YWRvID0gZmN0X3Jlb3JkZXIoZXN0YWRvLCBiZW5lZmljaWFyaW9zLCAuZGVzYyA9IFRSVUUpKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhiZW5lZmljaWFyaW9zKSkNCmBgYA0KDQojIyMgNGMuIFNjYXR0ZXJwbG90IG9mIG11bmljaXBhbGl0aWVzDQoqbG9nYXJpdGhtaWMgc2NhbGU7IGxhcmdlciBwb2ludHMgaW5kaWNhdGUgbW9yZSBiZW5lZmljaWFyaWVzIHJlYWNoZWQsIGRhcmtlciBibHVlcyBpbmRpY2F0ZSBtb3JlIGFjdGl2aXR5IHR5cGVzKiANCg0KKm1vdXNlIG92ZXIgbXVuaWNpcGFsaXRpZXMgdG8gc2VlIGJlbmVmaWNpYXJpZXMgYW5kIGRpc3RpbmN0IGFjdGl2aXRpZXMqDQoNCj4gQSB0b3RhbCBvZiBfX2ByIG5fZGlzdGluY3QodV9iZW4yJHBjb2RlMilgX18gbXVuaWNpcGFsaXRpZXMgd2VyZSByZWFjaGVkIGJ5IHRoZSBVTklDRUYgRWR1Y2F0aW9uIHByb2dyYW1tZS4NCg0KYGBge3Igc2NhdHRlci1QTE9UTFktb2YtbXVuaWNpcGFsaXRpZXMtYnktc3RhdGUsIGZpZy53aWR0aD05fQ0KDQphbGxfbXVuX3BvaW50cyA8LSBhbGxfbXVuICU+JSANCiAgZ2dwbG90KGFlcyh0ZXh0ID0gbXVuaWNpcGlvLCB4ID0gZXN0YWRvLCB5ID0gYmVuZWZpY2lhcmlvcywgDQogICAgICAgICAgICAgY29sb3VyID0gYWN0X3R5cGVzKSkgKw0KICBnZW9tX3BvaW50KGFlcyhzaXplID0gYmVuZWZpY2lhcmlvcyksIGFscGhhID0gMC45KSArDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudChsb3cgPSAiYXp1cmU0IiwgaGlnaCA9ICJkYXJrYmx1ZSIpICsgI2ZpbmQgYSBiZXR0ZXIgY29sb3VyPw0KICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCANCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGNvbW1hKSArDQogIHhsYWIoIiIpICsgeWxhYigiQmVuZWZpY2lhcmlvcyBBbGNhbnphZG9zIHBvciBNdW5pY2lwaW8iKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSANCg0KZ2dwbG90bHkoYWxsX211bl9wb2ludHMsIHRvb2x0aXAgPSBjKCJ0ZXh0IiwgInkiLCAiY29sb3VyIikpICU+JSANCiAgY29uZmlnKGRpc3BsYXlNb2RlQmFyID0gRkFMU0UpDQoNCmBgYA0KDQombmJzcDsNCg0KIyMjIDRkLiBUb3AgMTAgbXVuaWNpcGFsaXRpZXMgYnkgcmVhY2ggYW5kIGNvdmVyYWdlDQoNCmBgYHtyIG11bmljaXBhbGl0aWVzLXRvcC1UQUJMRX0NCiMgdG9wIG11bmljaXBhbGl0aWVzIHRhYmxlDQp0b3BfbXVuIDwtIGFsbF9tdW4gJT4lIHNlbGVjdChlc3RhZG8sIG11bmljaXBpbywgYmVuZWZpY2lhcmlvcykgJT4lIHNsaWNlKDE6MTApDQoNCiMgdHJ5IHRvIG1ha2UgYSB0YWJsZSBvZiB0aGUgbW9zdCBvdmVyc3Vic2NyaWJlZCBtdW5pY2lwYWxpdGllcw0KdG9wX2NvdiA8LSBhbGxfbXVuICU+JSANCiAgYXJyYW5nZShkZXNjKGNvdmVyYWdlX3BlcmNlbnQpKSAlPiUgDQogIHNlbGVjdChlc3RhZG8sIG11bmljaXBpbywgY292ZXJhZ2VfcGVyY2VudCkgJT4lIHNsaWNlKDE6MTApDQoNCiMgdHdvIHRhYmxlcyBzaWRlIGJ5IHNpZGUNCmthYmxlKHRvcF9tdW4sIGNhcHRpb24gPSAiYnkgYmVuZWZpY2lhcmllcyIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gImJvcmRlcmVkIiwgZnVsbF93aWR0aCA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9ICJmbG9hdF9sZWZ0IiwgZm9udF9zaXplID0gMTIpDQprYWJsZSh0b3BfY292LCBjYXB0aW9uID0gImJ5IGNvdmVyYWdlIikgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAiYm9yZGVyZWQiLCBmdWxsX3dpZHRoID0gRkFMU0UsIA0KICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImxlZnQiLCBmb250X3NpemUgPSAxMikNCmBgYA0KDQpgYGB7ciBSRUYtZm9yLXRleHQtYmVsb3d9DQojIHN1bSBvZiB0b3AgdGVuDQp0b3BfbXVuX3N1bSA8LSBhbGxfbXVuICU+JSANCiAgc2xpY2UoMToxMCkgJT4lIHN1bW1hcmlzZShzdW0gPSBzdW0oYmVuZWZpY2lhcmlvcywgbmEucm0gPSBUUlVFKSkNCg0KYWxsX211bl9zdW0gPC0gYWxsX211biAlPiUgDQogIHN1bW1hcmlzZShzdW0gPSBzdW0oYmVuZWZpY2lhcmlvcywgbmEucm0gPSBUUlVFKSkNCmBgYA0KDQo+IFRvZ2V0aGVyLCB0aGUgMTAgbXVuaWNpcGFsaXRpZXMgd2l0aCB0aGUgaGlnaGVzdCByZWFjaCAoYWJvdmUgbGVmdCkgZm9ybSBfX2ByIHJvdW5kKHRvcF9tdW5fc3VtIC8gYWxsX211bl9zdW0gKiAxMDApYCVfXyBvZiB0aGUgX19gciBmb3JtYXQocm91bmQoc3VtKHVfYmVuMiRiZW5lZmljaWFyaW9zKSksIGJpZy5tYXJrID0gIiwiKWBfXyBiZW5lZmljaWFyaWVzIHJlYWNoZWQuIFRoZSBhdmVyYWdlIGNvdmVyYWdlIG9mIHRoZSBzY2hvb2wtYWdlIHBvcHVsYXRpb24gaW4gdGhlIG11bmljaXBhbGl0aWVzIHdoZXJlIFVOSUNFRiBpcyBwcmVzZW50IGlzIF9fYHIgcm91bmQobWVhbihhbGxfbXVuJGNvdmVyYWdlX3BlcmNlbnQsIG5hLnJtID0gVFJVRSkpYCVfXy4gQ292ZXJhZ2UgcmVmZXJzIHRvIHRoZSBwZXJjZW50YWdlIG9mIGVucm9sbGVkIGNoaWxkcmVuIChhZ2VkIDMtMTcgeWVhcnMpIHJlYWNoZWQgYnkgVU5JQ0VGLiANCg0KJm5ic3A7DQoNCiMjIyA0ZS4gSGlzdG9ncmFtIG9mIENvdmVyYWdlDQoNCj4gQmVsb3cgaXMgYSBoaXN0b2dyYW0gb2YgbXVuY2lpcGFsaXRpZXMgd2hlcmUgVU5JQ0VGIGlzIHByZXNlbnQgc2hvd2luZyB0aGUgY292ZXJhZ2Ugb2YgZW5yb2xsZWQgY2hpbGRyZW4gKGFnZWQgMy0xNykuIE9mIG5vdGUsIHdlIGhhdmUgcmVhY2hlZCAxMCUgb3IgbGVzcyBvZiB0aGUgcG9wdWxhdGlvbiBpbiBfX2ByIHN1bShhbGxfbXVuJGNvdmVyYWdlX3BlcmNlbnQgPD0gMTAsIG5hLnJtID0gVFJVRSlgX18gb3V0IG9mIHRoZSBfX2ByIG5fZGlzdGluY3QodV9iZW4yJHBjb2RlMilgX18gaW4gd2hpY2ggd2Ugb3BlcmF0ZS4gVGhpcyBpcyBpbiBhZGRpdGlvbiB0byB0aGUgX19gciBzdW0oaXMubmEoYWxsX211biRjb3ZlcmFnZV9wZXJjZW50KSlgX18gd2hlcmUgbm8gVU5JQ0VGIEVkdWNhdGlvbiBhY3Rpdml0aWVzIGhhdmUgb2NjdXJyZWQuIA0KDQpgYGB7ciBQTE9ULWhpc3RvZ3JhbS1vZi1jb3ZlcmFnZX0NCmFsbF9tdW4gJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBjb3ZlcmFnZV9wZXJjZW50KSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwLCBjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gIndoaXRlIikgKw0KICBzdGF0X2JpbihiaW53aWR0aCA9IDEwLCBnZW9tID0gInRleHQiLCBhZXMobGFiZWwgPSAuLmNvdW50Li4pLCB2anVzdCA9IC0wLjUpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwgMTAsIDIwLCAzMCwgNDAsIDUwLCA2MCwgNzAsIDgwLCA5MCkpICsNCiAgeWxhYigiTnVtYmVyIG9mIG11bmljaXBhbGl0aWVzIikgKyB4bGFiKCJQZXJjZW50IG9mIGVucm9sbGVkIGNoaWxkcmVuICgzLTE3KSBjb3ZlcmVkIikNCg0KYGBgDQoNCiZuYnNwOw0KDQojIyA1LiBSZXBvcnRzIGFib3V0IHBhcnRuZXJzDQoNCiMjIyA1YS4gU3VtbWFyeSBieSBwYXJ0bmVyDQoNCmBgYHtyIFBMT1RMWS1zdGFja2VkLWJhci1wYXJ0bmVyLCBmaWcud2lkdGg9OX0NCiMgZm9yIHRoZSB0b3RhbHMgcGVyIHBhcnRuZXIgc2hvd3MgaW4gdGhlIGdlb21fdGV4dCBiZWxvdw0Kc3RhY2tfdGV4dCA8LSBhY3RfYmVuMiAlPiUgDQogIGdyb3VwX2J5KG9yZ2FuaXphY2lvbl9pbXBsZW1lbnRhZG9yYSkgJT4lIA0KICBzdW1tYXJpc2UodG90YWwgPSBzdW0oYmVuZWZpY2lhcmlvcykpICU+JSANCiAgYXJyYW5nZShkZXNjKHRvdGFsKSkNCg0KIyB2ZWN0b3IgZm9yIG9yZGVyaW5nIG9mIHgtYXhpcyAocGFydG5lcnMpDQpvcmRfc29jIDwtIGMoIlVOSUNFRiIsICJTT0NJTyAxIiwgIlNPQ0lPIDIiLCAiU09DSU8gNCIsICJTT0NJTyA1IiwgIlNPQ0lPIDciLCAiU09DSU8gOCIsDQogICAgICAgICAgICAgIlNPQ0lPIDMiLCAiU09DSU8gMTAiLCAiU09DSU8gNiIpDQoNCiMgY3JlYXRpbmcgdGhlIHBsb3QNCnNvY19zdGFjayA8LSBhY3RfYmVuMiAlPiUgDQogIGdyb3VwX2J5KGFjdGl2aWRhZF9zaG9ydCwgb3JnYW5pemFjaW9uX2ltcGxlbWVudGFkb3JhKSAlPiUgDQogIHN1bW1hcmlzZShiZW5lZmljaWFyaW9zID0gcm91bmQoc3VtKGJlbmVmaWNpYXJpb3MpKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IG9yZ2FuaXphY2lvbl9pbXBsZW1lbnRhZG9yYSwgDQogICAgICAgICAgICAgeSA9IGJlbmVmaWNpYXJpb3MpKSArDQogIGdlb21fY29sKGFlcyhmaWxsID0gYWN0aXZpZGFkX3Nob3J0KSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gdW5pdF9mb3JtYXQodW5pdCA9ICJLIiwgc2NhbGUgPSAxZS0zLCBzZXAgPSAiIiksIA0KICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLCA0MDAwMDApKSArDQogIHhsYWIoIiIpICsgeWxhYigiQmVuZWZpY2lhcmlvcyIpICsgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksDQogICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC4xLCAiY20iKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkgKw0KICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWUgPSAiQWN0aXZpZGFkIikgKw0KICBnZW9tX3RleHQoZGF0YSA9IHN0YWNrX3RleHQsIGFlcyh5ID0gdG90YWwgKyA2MDAwLCBsYWJlbCA9IHNjYWxlczo6Y29tbWEodG90YWwpKSwgDQogICAgICAgICAgICBzaXplID0gMykgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IG9yZF9zb2MpDQoNCmdncGxvdGx5KHNvY19zdGFjaywgdG9vbHRpcCA9IGMoIngiLCAiZmlsbCIsICJ5IikpICU+JSANCiAgbGF5b3V0KGxlZ2VuZCA9IGxpc3QodGl0bGUgPSBsaXN0KHRleHQgPSAiPGI+IG9yZ2FuaXphY2lvbiA8Yj4iKSkpICU+JSANCiAgY29uZmlnKGRpc3BsYXlNb2RlQmFyID0gRkFMU0UpICU+JSANCiAgbGF5b3V0KHNob3dsZWdlbmQgPSBUUlVFLCBsZWdlbmQgPSBsaXN0KGZvbnQgPSBsaXN0KHNpemUgPSA2KSkpDQoNCmBgYA0KDQombmJzcDsNCg0KIyMjIDViLiBOdW1iZXIgb2YgYWN0aXZpdHkgdHlwZXMgaW1wbGVtZW50ZWQgYnkgZWFjaCBwYXJ0bmVyDQoNCmBgYHtyIFRBQkxFLXBhcnRuZXItYWN0aXZpdHktY291bnR9DQojIHRoaXMgaW5jbHVkZXMgQ0ExLjA1DQphY3RfYmVuICU+JSANCiAgbXV0YXRlKG9yZ2FuaXphY2lvbl9pbXBsZW1lbnRhZG9yYSA9IA0KICAgICAgICAgICBzdHJfcmVwbGFjZV9hbGwob3JnYW5pemFjaW9uX2ltcGxlbWVudGFkb3JhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJVTklDRUYgLSBGb25kbyBkZSBsYXMgTmFjaW9uZXMgVW5pZGFzIHBhcmEgbGEgSW5mYW5jaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVOSUNFRiIpKSAlPiUgDQogIHJlbmFtZShwYXJ0bmVyID0gb3JnYW5pemFjaW9uX2ltcGxlbWVudGFkb3JhKSAlPiUgDQogIGdyb3VwX2J5KHBhcnRuZXIpICU+JSANCiAgc3VtbWFyaXNlKGFjdF90eXBlcyA9IG5fZGlzdGluY3QoYWN0aXZpZGFkX2NvZGlnbykpICU+JSANCiAgYXJyYW5nZShkZXNjKGFjdF90eXBlcykpICU+JSANCiAgdCgpICU+JSANCiAgcGFuZGVyKCkNCg0KYGBgDQoNCiZuYnNwOw0KDQojIyMgNWMuIFBhcnRuZXJzJyBwcm9ncmVzcyBvdmVyIHRpbWUNCiptb3VzZSBvdmVyIGZvciBkZXRhaWxzKg0KDQpgYGB7ciBsaW5lLVBMT1RMWS1wYXJ0bmVycy1wcm9ncmVzcywgZmlnLndpZHRoPTl9DQoNCnNvY19saW5lIDwtIGFjdF9iZW4yICU+JSANCiAgbXV0YXRlKG1lc19zb2xvID0gYXMuRGF0ZShtZXNfc29sbykpICU+JSANCiAgZ3JvdXBfYnkob3JnYW5pemFjaW9uX2ltcGxlbWVudGFkb3JhLCBtZXNfc29sbykgJT4lIA0KICBzdW1tYXJpc2UoY3VtdWxhdGl2ZSA9IHJvdW5kKHN1bShiZW5lZmljaWFyaW9zKSkpICU+JSANCiAgbXV0YXRlKGN1bXVsYXRpdmUgPSBjdW1zdW0oY3VtdWxhdGl2ZSkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gbWVzX3NvbG8sIHkgPSBjdW11bGF0aXZlLCBjb2xvdXIgPSBvcmdhbml6YWNpb25faW1wbGVtZW50YWRvcmEpKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMC43KSArDQogIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlYi0lWSIsIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSB1bml0X2Zvcm1hdCh1bml0ID0gIksiLCBzY2FsZSA9IDFlLTMsIHNlcCA9ICIiKSwgDQogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsIDQxMDAwMCkpICsNCiAgeGxhYigiIikgKyB5bGFiKCJCZW5lZmljaWFyaW9zIikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYpLA0KICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKQ0KDQpnZ3Bsb3RseShzb2NfbGluZSwgdG9vbHRpcCA9IGMoIngiLCAieSIsICJjb2xvdXIiKSkgJT4lIA0KICBsYXlvdXQobGVnZW5kID0gbGlzdCh0aXRsZSA9IGxpc3QodGV4dCA9ICI8Yj4gb3JnYW5pemFjaW9uIDxiPiIpKSkgJT4lIA0KICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkNCiAgDQpgYGANCg0KJm5ic3A7DQoNCiMjIyA1ZC4gU3VtbWFyeSB0YWJsZSBvZiBwYXJ0bmVycycgYWNoaWV2ZW1lbnRzDQoNCmBgYHtyIFRBQkxFLXBhcnRuZXJzLXN1bW1hcnl9DQphY3RfYmVuMiAlPiUgDQogIG11dGF0ZShzZXhfYmVuID0gaWZlbHNlKHN0cl9kZXRlY3QoZGVzYWdyZWdhY2lvbiwgIl5tIiksICJtYWxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHN0cl9kZXRlY3QoZGVzYWdyZWdhY2lvbiwgIl5mIiksICJmZW1hbGUiLCAibm9fZXNwIikpKSAlPiUgDQogIG11dGF0ZShhY3RpdmlkYWQgPSBhY3RpdmlkYWRfZGVzYykgJT4lIA0KICBncm91cF9ieShvcmdhbml6YWNpb25faW1wbGVtZW50YWRvcmEpICU+JSANCiAgc3VtbWFyaXNlKG1hbGUgPSBzdW0oKGJlbmVmaWNpYXJpb3Nbc2V4X2JlbiA9PSAibWFsZSJdKSksDQogICAgICAgICAgICBmZW1hbGUgPSBzdW0oKGJlbmVmaWNpYXJpb3Nbc2V4X2JlbiA9PSAiZmVtYWxlIl0pKSwNCiAgICAgICAgICAgIHNleF9yYXRpbyA9IHJvdW5kKChtYWxlL2ZlbWFsZSksIGRpZ2l0cyA9IDIpLA0KICAgICAgICAgICAgYmVuZWZpY2lhcmlvcyA9IHN1bShiZW5lZmljaWFyaW9zLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIG11dGF0ZShwZXJjZW50X29mX3RvdGFsID0gcm91bmQoKGJlbmVmaWNpYXJpb3MgLyBzdW0oYmVuZWZpY2lhcmlvcykgKiAxMDApLCBkaWdpdHMgPSAyKSkgJT4lIA0KICBsZWZ0X2pvaW4oYWN0X2JlbiAlPiUgDQogICAgICAgICAgICAgIG11dGF0ZShvcmdhbml6YWNpb25faW1wbGVtZW50YWRvcmEgPSANCiAgICAgICAgICAgICAgc3RyX3JlcGxhY2VfYWxsKG9yZ2FuaXphY2lvbl9pbXBsZW1lbnRhZG9yYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAiVU5JQ0VGIC0gRm9uZG8gZGUgbGFzIE5hY2lvbmVzIFVuaWRhcyBwYXJhIGxhIEluZmFuY2lhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJVTklDRUYiKSkgJT4lIA0KICAgICAgICAgICAgICBncm91cF9ieShvcmdhbml6YWNpb25faW1wbGVtZW50YWRvcmEpICU+JSANCiAgICAgICAgICAgICAgc3VtbWFyaXNlKG11bmljaXBhbGl0aWVzID0gbl9kaXN0aW5jdChwY29kZTIpKSwgDQogICAgIGJ5ID0gIm9yZ2FuaXphY2lvbl9pbXBsZW1lbnRhZG9yYSIpICU+JSANCiAgcmVsb2NhdGUoYmVuZWZpY2lhcmlvcywgLmFmdGVyID0gb3JnYW5pemFjaW9uX2ltcGxlbWVudGFkb3JhKSAlPiUgDQogIHJlbG9jYXRlKHBlcmNlbnRfb2ZfdG90YWwsIC5hZnRlciA9IGJlbmVmaWNpYXJpb3MpICU+JSANCiAgYXJyYW5nZShkZXNjKGJlbmVmaWNpYXJpb3MpKSAlPiUgDQogIHBhbmRlcihiaWcubWFyayA9ICIsIiwgc3R5bGUgPSAicm1hcmtkb3duIikNCmBgYA0KDQombmJzcDsNCg0KIyMgNi4gTWFwcyBhbmQgcmVmZXJlbmNlIHRhYmxlDQoNCiZuYnNwOw0KDQojIyMgNmEuIE1hcHMgYXQgbXVuaWNpcGFsIGxldmVsDQoNCmBgYHtyIE1BUFMtbXVuLXJlYWNoZWQtYW5kLXBlcmNlbnQtcmVhY2hlZH0NCg0KIyByZWFkaW5nIGluIHNoYXBlZmlsZQ0KIyBxdWlldCA9IFRSVUUgaXMgdmVyeSBpbXBvcnRhbnQgaGVyZQ0KcGNvZGUyX3NoYXBlIDwtIHN0X3JlYWQoIkM6L1VzZXJzL1NlYW4gTmcvRG9jdW1lbnRzL1IvNVcvdm56X2FkbTJfc2hhcGVmaWxlcy92ZW5fYWRtYm5kYV9hZG0yXzIwMTgwNTAyLnNocCIsIHF1aWV0ID0gVFJVRSkgJT4lIA0KICByZW5hbWUocGNvZGUxID0gQURNMV9QQ09ERSwNCiAgICAgICAgIHBjb2RlMiA9IEFETTJfUENPREUpDQoNCiMgSSB0aGluayBwbG90bHkncyBzZWxlY3RvciB0b29sIGlzIG5vdCB2ZXJ5IGdvb2QuIG9yIG1heWJlIHRoZSBjZW50cm9pZHMNCiMgb2YgdGhlIHZlbl9hZG1ibmRhIGRhdGFzZXQgaXMgbm90IHZlcnkgZ29vZCwgYXQgbGVhc3Qgd2hlbiBpdCBjb21lcyB0byBjZW50cm9pZHMuIA0KDQojIHBsb3QgZm9yIGJlbmVmaWNpYXJpZXMgcmVhY2hlZCBieSBwY29kZTINCm11bl9iZW5fcGxvdCA8LSBhbGxfbXVuICU+JSANCiAgcmlnaHRfam9pbihwY29kZTJfc2hhcGUpICU+JSANCiAgc3RfYXNfc2YoKSAlPiUgDQogIGdncGxvdChhZXMoZmlsbCA9IGJlbmVmaWNpYXJpb3MpKSArDQogIGdlb21fc2Yoc2l6ZSA9IDAuMDEpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgZ2d0aXRsZSgiTnVtYmVyIG9mIGJlbmVmaWNpYXJpZXMgcmVhY2hlZCBieSBtdW5pY2lwYWxpdHkiKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQodHJhbnMgPSB0cmFuc19yZXZlcnNlcigibG9nIiksIGJyZWFrcyA9IGMoMCwgMTAwLCAxMDAwLCAxMDAwMCwgODA0ODIpLA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGNvbW1hLCBuYS52YWx1ZSA9ICJncmF5OTAiKSArDQogIHRoZW1lKGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC4zLCAiY20iKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjksIDAuMSksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpKQ0KDQojIG1hcCBvZiBwZXJjZW50IG9mIGVucm9sbGVkIGNoaWRyZW4gY292ZXJlZCBieSBwY29kZTINCm11bl9wZXJjZW50X3Bsb3QgPC0gYWxsX211biAlPiUgDQogIHJpZ2h0X2pvaW4ocGNvZGUyX3NoYXBlKSAlPiUgDQogIHN0X2FzX3NmKCkgJT4lDQogIGdncGxvdChhZXMoZmlsbCA9IGNvdmVyYWdlX3BlcmNlbnQpKSsNCiAgZ2VvbV9zZihzaXplID0gMC4wMSkgKw0KICB0aGVtZV92b2lkKCkgKw0KICBnZ3RpdGxlKCJQZXJjZW50IG9mIGVucm9sbGVkIGNoaWxkcmVuICgzLTE3KSByZWFjaGVkIGJ5IG11bmljaXBhbGl0eSIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsYWJlbHMgPSBjb21tYSwgdHJhbnMgPSAicmV2ZXJzZSIsIG5hLnZhbHVlID0gImdyYXk5MCIpKw0KICB0aGVtZShsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuMywgImNtIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC45LCAwLjEpLA0KICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpDQoNCiMgdXNpbmcgcGF0Y2h3b3JrIHRvIHB1dCB0aGVtIHNpZGUgYnkgc2lkZSANCm11bl9iZW5fcGxvdCArIG11bl9wZXJjZW50X3Bsb3QgKyBwbG90X2xheW91dChuY29sID0gMikNCmBgYA0KDQombmJzcDsNCg0KIyMjIDZiLiBSZWZlcmVuY2UgdGFibGUgLSBtdW5pY2lwYWwgbGV2ZWwNCg0KX191c2UgYFVOSUNFRl9wcmVzZW50YCB0byBmaWx0ZXIgdG8gbXVuaWNpcGFsaXRpZXMgd2hlcmUgdGhlIEVkdWNhdGlvbiBwcm9ncmFtbWUgb3BlcmF0ZXNfXw0KDQoqQ0EwMS4wNSBQcm9tb2Npb24gZGUgbWVuc2FqZXMgY2xhdmVzIHBhcmEgbGEgY29tdW5pZGFkIGVzY29sYXIgaXMgbm90IGluY2x1ZGVkKg0KDQpgYGB7ciBEVC1kYXRhdGFibGV9DQoNCiMgaXQgc2hvd3MgMzM1LCBzaG91bGRuJ3QgdGhlcmUgYmUgMzM2PyBJIGJldCBpdCdzIFZhcmdhcyBhZ2Fpbg0KYWxsX211biAlPiUgDQogIG11dGF0ZShVTklDRUZfcHJlc2VudCA9IGlmZWxzZShpcy5uYShiZW5lZmljaWFyaW9zKSwgRkFMU0UsIFRSVUUpKSAlPiUgDQogIHJlbmFtZShub19vZl9hY3Rpdml0aWVzID0gYWN0X3R5cGVzKSAlPiUgIyBJIGZlZWwgbGlrZSB5b3Ugc2hvdWxkIGhhdmUgZG9uZSB0aGlzIGVhcmxpZXINCiAgbGVmdF9qb2luKGNlbl9yZWYgJT4lICMgYWRkaXRpb25hbCBjZW5zdXMgdmFyaWFibGVzDQogICAgICBncm91cF9ieShwY29kZTIpICU+JSANCiAgICAgIHN1bW1hcmlzZShwb29yX3BlcnNvbnMgPSByb3VuZChzdW0oaGFtXzIwMTlfeHhfcG9ibGFjaW9uX3BvYnJlX3Bvcl9wYXJyb3F1aWEpKSwNCiAgICAgICAgICAgICAgICB0b3RhbF9wb3AgICAgPSBzdW0oeF8yMDE5X3BvYmxhY2lvbl9wYXJyb3F1aWFsX3RvdGFsKSkgJT4lIA0KICAgICAgbXV0YXRlKHBvdmVydHlfaW5jaWRlbmNlID0gcm91bmQocG9vcl9wZXJzb25zIC8gdG90YWxfcG9wICogMTAwKSkpICU+JSANCiAgc2VsZWN0KCFwY29kZTIpICU+JQ0KICByZWxvY2F0ZShVTklDRUZfcHJlc2VudCkgJT4lIA0KICByZWxvY2F0ZShwb3ZlcnR5X2luY2lkZW5jZSwgLmFmdGVyID0gY292ZXJhZ2VfcGVyY2VudCkgJT4lIA0KICByZWxvY2F0ZShub19vZl9hY3Rpdml0aWVzLCAuYWZ0ZXIgPSBwb3ZlcnR5X2luY2lkZW5jZSkgJT4lDQogIGRhdGF0YWJsZShmaWx0ZXIgPSAidG9wIiwgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDEwLCBzY3JvbGxYID0gVFJVRSkpICU+JSANCiAgRFQ6OmZvcm1hdFN0eWxlKGNvbHVtbnMgPSBjb2xuYW1lcyguKSwgZm9udFNpemUgPSAiMTJwdCIpDQogIA0KYGBgDQoNCg==